From 04ce69093f91547d3a7c4fc815d2868195591340 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 8 Nov 2006 00:21:01 -0800 Subject: [IPV6]: 'info' argument of ipv6 ->err_handler() is net-endian Signed-off-by: Al Viro Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 4c2a7c0cafe..eb6d145ecfd 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -310,7 +310,7 @@ failure: } static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); -- cgit v1.2.3-70-g09d2 From 72a3effaf633bcae9034b7e176bdbd78d64a71db Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 16 Nov 2006 02:30:37 -0800 Subject: [NET]: Size listen hash tables using backlog hint We currently allocate a fixed size (TCP_SYNQ_HSIZE=512) slots hash table for each LISTEN socket, regardless of various parameters (listen backlog for example) On x86_64, this means order-1 allocations (might fail), even for 'small' sockets, expecting few connections. On the contrary, a huge server wanting a backlog of 50000 is slowed down a bit because of this fixed limit. This patch makes the sizing of listen hash table a dynamic parameter, depending of : - net.core.somaxconn tunable (default is 128) - net.ipv4.tcp_max_syn_backlog tunable (default : 256, 1024 or 128) - backlog value given by user application (2nd parameter of listen()) For large allocations (bigger than PAGE_SIZE), we use vmalloc() instead of kmalloc(). We still limit memory allocation with the two existing tunables (somaxconn & tcp_max_syn_backlog). So for standard setups, this patch actually reduce RAM usage. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/request_sock.h | 8 ++++---- include/net/tcp.h | 1 - net/core/request_sock.c | 35 +++++++++++++++++++++++++---------- net/dccp/ipv4.c | 2 +- net/dccp/proto.c | 6 +++--- net/ipv4/af_inet.c | 2 +- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/tcp_ipv4.c | 6 +++--- net/ipv6/tcp_ipv6.c | 2 +- 9 files changed, 39 insertions(+), 25 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/net/request_sock.h b/include/net/request_sock.h index f743a941a4f..b5b023e79e5 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -28,8 +28,8 @@ struct proto; struct request_sock_ops { int family; - kmem_cache_t *slab; int obj_size; + kmem_cache_t *slab; int (*rtx_syn_ack)(struct sock *sk, struct request_sock *req, struct dst_entry *dst); @@ -51,13 +51,13 @@ struct request_sock { u32 rcv_wnd; /* rcv_wnd offered first time */ u32 ts_recent; unsigned long expires; - struct request_sock_ops *rsk_ops; + const struct request_sock_ops *rsk_ops; struct sock *sk; u32 secid; u32 peer_secid; }; -static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops) +static inline struct request_sock *reqsk_alloc(const struct request_sock_ops *ops) { struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC); @@ -121,7 +121,7 @@ struct request_sock_queue { }; extern int reqsk_queue_alloc(struct request_sock_queue *queue, - const int nr_table_entries); + unsigned int nr_table_entries); static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue) { diff --git a/include/net/tcp.h b/include/net/tcp.h index 7a093d0aa0f..246916c2321 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -138,7 +138,6 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define MAX_TCP_SYNCNT 127 #define TCP_SYNQ_INTERVAL (HZ/5) /* Period of SYNACK timer */ -#define TCP_SYNQ_HSIZE 512 /* Size of SYNACK hash table */ #define TCP_PAWS_24DAYS (60 * 60 * 24 * 24) #define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 79ebd75fbe4..5f0818d815e 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -29,22 +30,31 @@ * it is absolutely not enough even at 100conn/sec. 256 cures most * of problems. This value is adjusted to 128 for very small machines * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb). - * Further increasing requires to change hash table size. + * Note : Dont forget somaxconn that may limit backlog too. */ int sysctl_max_syn_backlog = 256; int reqsk_queue_alloc(struct request_sock_queue *queue, - const int nr_table_entries) + unsigned int nr_table_entries) { - const int lopt_size = sizeof(struct listen_sock) + - nr_table_entries * sizeof(struct request_sock *); - struct listen_sock *lopt = kzalloc(lopt_size, GFP_KERNEL); - + size_t lopt_size = sizeof(struct listen_sock); + struct listen_sock *lopt; + + nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); + nr_table_entries = max_t(u32, nr_table_entries, 8); + nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); + lopt_size += nr_table_entries * sizeof(struct request_sock *); + if (lopt_size > PAGE_SIZE) + lopt = __vmalloc(lopt_size, + GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, + PAGE_KERNEL); + else + lopt = kzalloc(lopt_size, GFP_KERNEL); if (lopt == NULL) return -ENOMEM; - for (lopt->max_qlen_log = 6; - (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog; + for (lopt->max_qlen_log = 3; + (1 << lopt->max_qlen_log) < nr_table_entries; lopt->max_qlen_log++); get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); @@ -65,9 +75,11 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) { /* make all the listen_opt local to us */ struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); + size_t lopt_size = sizeof(struct listen_sock) + + lopt->nr_table_entries * sizeof(struct request_sock *); if (lopt->qlen != 0) { - int i; + unsigned int i; for (i = 0; i < lopt->nr_table_entries; i++) { struct request_sock *req; @@ -81,7 +93,10 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) } BUG_TRAP(lopt->qlen == 0); - kfree(lopt); + if (lopt_size > PAGE_SIZE) + vfree(lopt); + else + kfree(lopt); } EXPORT_SYMBOL(reqsk_queue_destroy); diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index e08e7688a26..0a5d68dbb41 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -1022,7 +1022,7 @@ static void dccp_v4_reqsk_destructor(struct request_sock *req) kfree(inet_rsk(req)->opt); } -static struct request_sock_ops dccp_request_sock_ops = { +static struct request_sock_ops dccp_request_sock_ops _read_mostly = { .family = PF_INET, .obj_size = sizeof(struct dccp_request_sock), .rtx_syn_ack = dccp_v4_send_response, diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 72cbdcfc2c6..047d170a363 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -262,12 +262,12 @@ int dccp_destroy_sock(struct sock *sk) EXPORT_SYMBOL_GPL(dccp_destroy_sock); -static inline int dccp_listen_start(struct sock *sk) +static inline int dccp_listen_start(struct sock *sk, int backlog) { struct dccp_sock *dp = dccp_sk(sk); dp->dccps_role = DCCP_ROLE_LISTEN; - return inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); + return inet_csk_listen_start(sk, backlog); } int dccp_disconnect(struct sock *sk, int flags) @@ -788,7 +788,7 @@ int inet_dccp_listen(struct socket *sock, int backlog) * FIXME: here it probably should be sk->sk_prot->listen_start * see tcp_listen_start */ - err = dccp_listen_start(sk); + err = dccp_listen_start(sk, backlog); if (err) goto out; } diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index edcf0932ac6..4a81d54a756 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -204,7 +204,7 @@ int inet_listen(struct socket *sock, int backlog) * we can only allow the backlog to be adjusted. */ if (old_state != TCP_LISTEN) { - err = inet_csk_listen_start(sk, TCP_SYNQ_HSIZE); + err = inet_csk_listen_start(sk, backlog); if (err) goto out; } diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 96bbe2a0aa1..9d68837888d 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -343,7 +343,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, EXPORT_SYMBOL_GPL(inet_csk_route_req); static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, - const u32 rnd, const u16 synq_hsize) + const u32 rnd, const u32 synq_hsize) { return jhash_2words((__force u32)raddr, (__force u32)rport, rnd) & (synq_hsize - 1); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 22ef8bd2662..5fbf96552ca 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -715,7 +715,7 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, return dopt; } -struct request_sock_ops tcp_request_sock_ops = { +struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), .rtx_syn_ack = tcp_v4_send_synack, @@ -1385,7 +1385,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) if (st->state == TCP_SEQ_STATE_OPENREQ) { struct request_sock *req = cur; - icsk = inet_csk(st->syn_wait_sk); + icsk = inet_csk(st->syn_wait_sk); req = req->dl_next; while (1) { while (req) { @@ -1395,7 +1395,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) } req = req->dl_next; } - if (++st->sbucket >= TCP_SYNQ_HSIZE) + if (++st->sbucket >= icsk->icsk_accept_queue.listen_opt->nr_table_entries) break; get_req: req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index eb6d145ecfd..1a3c46c139f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -526,7 +526,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static struct request_sock_ops tcp6_request_sock_ops = { +static struct request_sock_ops tcp6_request_sock_ops _read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), .rtx_syn_ack = tcp_v6_send_synack, -- cgit v1.2.3-70-g09d2 From 9ec75fe85c58471db958386c1604e5006a2e2f69 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 9 Nov 2006 16:26:09 -0800 Subject: [IPV6] tcp: Fix typo _read_mostly --> __read_mostly. Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1a3c46c139f..06b536b47f9 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -526,7 +526,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static struct request_sock_ops tcp6_request_sock_ops _read_mostly = { +static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), .rtx_syn_ack = tcp_v6_send_synack, -- cgit v1.2.3-70-g09d2 From a94f723d595ee085f81b1788d18e031af7eeba91 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Fri, 10 Nov 2006 14:06:49 -0800 Subject: [TCP]: Remove dead code in init_sequence This removes two redundancies: 1) The test (skb->protocol == htons(ETH_P_IPV6) in tcp_v6_init_sequence() is always true, due to * tcp_v6_conn_request() is the only function calling this one * tcp_v6_conn_request() redirects all skb's with ETH_P_IP protocol to tcp_v4_conn_request() [ cf. top of tcp_v6_conn_request()] 2) The first argument, `struct sock *sk' of tcp_v{4,6}_init_sequence() is never used. Signed-off-by: Gerrit Renker Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv6/tcp_ipv6.c | 19 ++++++------------- 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5fbf96552ca..2eb58844403 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -111,7 +111,7 @@ void tcp_unhash(struct sock *sk) inet_unhash(&tcp_hashinfo, sk); } -static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) +static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb) { return secure_tcp_sequence_number(skb->nh.iph->daddr, skb->nh.iph->saddr, @@ -859,7 +859,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free; } - isn = tcp_v4_init_sequence(sk, skb); + isn = tcp_v4_init_sequence(skb); } tcp_rsk(req)->snt_isn = isn; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 06b536b47f9..9a8e690fdf7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -106,19 +106,12 @@ static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); } -static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb) +static __u32 tcp_v6_init_sequence(struct sk_buff *skb) { - if (skb->protocol == htons(ETH_P_IPV6)) { - return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, - skb->nh.ipv6h->saddr.s6_addr32, - skb->h.th->dest, - skb->h.th->source); - } else { - return secure_tcp_sequence_number(skb->nh.iph->daddr, - skb->nh.iph->saddr, - skb->h.th->dest, - skb->h.th->source); - } + return secure_tcpv6_sequence_number(skb->nh.ipv6h->daddr.s6_addr32, + skb->nh.ipv6h->saddr.s6_addr32, + skb->h.th->dest, + skb->h.th->source); } static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, @@ -822,7 +815,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) treq->iif = inet6_iif(skb); if (isn == 0) - isn = tcp_v6_init_sequence(sk,skb); + isn = tcp_v6_init_sequence(skb); tcp_rsk(req)->snt_isn = isn; -- cgit v1.2.3-70-g09d2 From b9df3cb8cf9a96e63dfdcd3056a9cbc71f2459e7 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 14 Nov 2006 11:21:36 -0200 Subject: [TCP/DCCP]: Introduce net_xmit_eval Throughout the TCP/DCCP (and tunnelling) code, it often happens that the return code of a transmit function needs to be tested against NET_XMIT_CN which is a value that does not indicate a strict error condition. This patch uses a macro for these recurring situations which is consistent with the already existing macro net_xmit_errno, saving on duplicated code. Signed-off-by: Gerrit Renker Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/netdevice.h | 4 ++++ include/net/ipip.h | 2 +- net/dccp/ipv4.c | 5 ++--- net/dccp/ipv6.c | 3 +-- net/dccp/output.c | 14 ++------------ net/ipv4/tcp_ipv4.c | 3 +-- net/ipv4/tcp_output.c | 8 +------- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/tcp_ipv6.c | 3 +-- 9 files changed, 14 insertions(+), 30 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4e967b2e22c..caa3c259371 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -66,6 +66,10 @@ struct netpoll_info; #define NET_RX_CN_HIGH 4 /* The storm is here */ #define NET_RX_BAD 5 /* packet dropped due to kernel error */ +/* NET_XMIT_CN is special. It does not guarantee that this packet is lost. It + * indicates that the device will soon be dropping packets, or already drops + * some packets of the same priority; prompting us to send less aggressively. */ +#define net_xmit_eval(e) ((e) == NET_XMIT_CN? 0 : (e)) #define net_xmit_errno(e) ((e) != NET_XMIT_CN ? -ENOBUFS : 0) #endif diff --git a/include/net/ipip.h b/include/net/ipip.h index f490c3cbe37..84058858eea 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -35,7 +35,7 @@ struct ip_tunnel ip_send_check(iph); \ \ err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output);\ - if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { \ + if (net_xmit_eval(err) == 0) { \ stats->tx_bytes += pkt_len; \ stats->tx_packets++; \ } else { \ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index bc400b2ba25..61c09014dad 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -501,8 +501,7 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req, err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } out: @@ -571,7 +570,7 @@ static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) rxskb->nh.iph->saddr, NULL); bh_unlock_sock(dccp_v4_ctl_socket->sk); - if (err == NET_XMIT_CN || err == 0) { + if (net_xmit_eval(err) == 0) { DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS); DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS); } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 8d6ddb6389a..2165b1740c7 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -294,8 +294,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req, &ireq6->rmt_addr); ipv6_addr_copy(&fl.fl6_dst, &ireq6->rmt_addr); err = ip6_xmit(sk, skb, &fl, opt, 0); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } done: diff --git a/net/dccp/output.c b/net/dccp/output.c index 0994b13f0f1..ef22f3cc791 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -125,16 +125,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = icsk->icsk_af_ops->queue_xmit(skb, sk, 0); - if (err <= 0) - return err; - - /* NET_XMIT_CN is special. It does not guarantee, - * that this packet is lost. It tells that device - * is about to start to drop packets or already - * drops some packets of the same priority and - * invokes us to send less aggressively. - */ - return err == NET_XMIT_CN ? 0 : err; + return net_xmit_eval(err); } return -ENOBUFS; } @@ -426,8 +417,7 @@ int dccp_send_reset(struct sock *sk, enum dccp_reset_codes code) if (skb != NULL) { memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); err = inet_csk(sk)->icsk_af_ops->queue_xmit(skb, sk, 0); - if (err == NET_XMIT_CN) - err = 0; + return net_xmit_eval(err); } } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 2eb58844403..0ad0904bf56 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -662,8 +662,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, ireq->rmt_addr, ireq->opt); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } out: diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f63e99aac2d..6a8581ab9a2 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -484,13 +484,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, tcp_enter_cwr(sk); - /* NET_XMIT_CN is special. It does not guarantee, - * that this packet is lost. It tells that device - * is about to start to drop packets or already - * drops some packets of the same priority and - * invokes us to send less aggressively. - */ - return err == NET_XMIT_CN ? 0 : err; + return net_xmit_eval(err); #undef SYSCTL_FLAG_TSTAMPS #undef SYSCTL_FLAG_WSCALE diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 4919f9294e2..80a11909159 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -748,7 +748,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output); - if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { + if (net_xmit_eval(err) == 0) { stats->tx_bytes += pkt_len; stats->tx_packets++; } else { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9a8e690fdf7..9a88395a762 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -502,8 +502,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr); err = ip6_xmit(sk, skb, &fl, opt, 0); - if (err == NET_XMIT_CN) - err = 0; + err = net_xmit_eval(err); } done: -- cgit v1.2.3-70-g09d2 From cfb6eeb4c860592edd123fdea908d23c6ad1c7dc Mon Sep 17 00:00:00 2001 From: YOSHIFUJI Hideaki Date: Tue, 14 Nov 2006 19:07:45 -0800 Subject: [TCP]: MD5 Signature Option (RFC2385) support. Based on implementation by Rick Payne. Signed-off-by: YOSHIFUJI Hideaki Signed-off-by: David S. Miller --- CREDITS | 3 + include/linux/tcp.h | 35 ++- include/net/request_sock.h | 3 +- include/net/tcp.h | 143 ++++++++++ include/net/timewait_sock.h | 3 + net/dccp/ipv4.c | 6 +- net/dccp/ipv6.c | 6 +- net/dccp/minisocks.c | 2 +- net/ipv4/Kconfig | 16 ++ net/ipv4/tcp.c | 137 +++++++++ net/ipv4/tcp_input.c | 8 + net/ipv4/tcp_ipv4.c | 673 ++++++++++++++++++++++++++++++++++++++++++-- net/ipv4/tcp_minisocks.c | 64 ++++- net/ipv4/tcp_output.c | 111 +++++++- net/ipv6/tcp_ipv6.c | 568 +++++++++++++++++++++++++++++++++++-- 15 files changed, 1714 insertions(+), 64 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/CREDITS b/CREDITS index ccd4f9f4dd7..d0880082c19 100644 --- a/CREDITS +++ b/CREDITS @@ -2598,6 +2598,9 @@ S: Ucitelska 1576 S: Prague 8 S: 182 00 Czech Republic +N: Rick Payne +D: RFC2385 Support for TCP + N: Barak A. Pearlmutter E: bap@cs.unm.edu W: http://www.cs.unm.edu/~bap/ diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 2d36f6db370..0aecfc95559 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -19,6 +19,7 @@ #include #include +#include struct tcphdr { __be16 source; @@ -94,6 +95,7 @@ enum { #define TCP_INFO 11 /* Information about this connection. */ #define TCP_QUICKACK 12 /* Block/reenable quick acks */ #define TCP_CONGESTION 13 /* Congestion control algorithm */ +#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ #define TCPI_OPT_TIMESTAMPS 1 #define TCPI_OPT_SACK 2 @@ -157,6 +159,17 @@ struct tcp_info __u32 tcpi_total_retrans; }; +/* for TCP_MD5SIG socket option */ +#define TCP_MD5SIG_MAXKEYLEN 80 + +struct tcp_md5sig { + struct __kernel_sockaddr_storage tcpm_addr; /* address associated */ + __u16 __tcpm_pad1; /* zero */ + __u16 tcpm_keylen; /* key length */ + __u32 __tcpm_pad2; /* zero */ + __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */ +}; + #ifdef __KERNEL__ #include @@ -197,9 +210,13 @@ struct tcp_options_received { }; struct tcp_request_sock { - struct inet_request_sock req; - __u32 rcv_isn; - __u32 snt_isn; + struct inet_request_sock req; +#ifdef CONFIG_TCP_MD5SIG + /* Only used by TCP MD5 Signature so far. */ + struct tcp_request_sock_ops *af_specific; +#endif + __u32 rcv_isn; + __u32 snt_isn; }; static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req) @@ -363,6 +380,14 @@ struct tcp_sock { __u32 probe_seq_start; __u32 probe_seq_end; } mtu_probe; + +#ifdef CONFIG_TCP_MD5SIG +/* TCP AF-Specific parts; only used by MD5 Signature support so far */ + struct tcp_sock_af_ops *af_specific; + +/* TCP MD5 Signagure Option information */ + struct tcp_md5sig_info *md5sig_info; +#endif }; static inline struct tcp_sock *tcp_sk(const struct sock *sk) @@ -377,6 +402,10 @@ struct tcp_timewait_sock { __u32 tw_rcv_wnd; __u32 tw_ts_recent; long tw_ts_recent_stamp; +#ifdef CONFIG_TCP_MD5SIG + __u16 tw_md5_keylen; + __u8 tw_md5_key[TCP_MD5SIG_MAXKEYLEN]; +#endif }; static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk) diff --git a/include/net/request_sock.h b/include/net/request_sock.h index b5b023e79e5..e37baaf2080 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h @@ -35,7 +35,8 @@ struct request_sock_ops { struct dst_entry *dst); void (*send_ack)(struct sk_buff *skb, struct request_sock *req); - void (*send_reset)(struct sk_buff *skb); + void (*send_reset)(struct sock *sk, + struct sk_buff *skb); void (*destructor)(struct request_sock *req); }; diff --git a/include/net/tcp.h b/include/net/tcp.h index e1a5d29d0a1..363960872de 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOPT_SACK_PERM 4 /* SACK Permitted */ #define TCPOPT_SACK 5 /* SACK Block */ #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ +#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ /* * TCP option lengths @@ -170,6 +172,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOLEN_WINDOW 3 #define TCPOLEN_SACK_PERM 2 #define TCPOLEN_TIMESTAMP 10 +#define TCPOLEN_MD5SIG 18 /* But this is what stacks really send out. */ #define TCPOLEN_TSTAMP_ALIGNED 12 @@ -178,6 +181,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOLEN_SACK_BASE 2 #define TCPOLEN_SACK_BASE_ALIGNED 4 #define TCPOLEN_SACK_PERBLOCK 8 +#define TCPOLEN_MD5SIG_ALIGNED 20 /* Flags in tp->nonagle */ #define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */ @@ -299,6 +303,8 @@ extern void tcp_cleanup_rbuf(struct sock *sk, int copied); extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp); +extern void tcp_twsk_destructor(struct sock *sk); + static inline void tcp_dec_quickack_mode(struct sock *sk, const unsigned int pkts) { @@ -1064,6 +1070,114 @@ static inline void clear_all_retrans_hints(struct tcp_sock *tp){ tp->fastpath_skb_hint = NULL; } +/* MD5 Signature */ +struct crypto_hash; + +/* - key database */ +struct tcp_md5sig_key { + u8 *key; + u8 keylen; +}; + +struct tcp4_md5sig_key { + u8 *key; + u16 keylen; + __be32 addr; +}; + +struct tcp6_md5sig_key { + u8 *key; + u16 keylen; +#if 0 + u32 scope_id; /* XXX */ +#endif + struct in6_addr addr; +}; + +/* - sock block */ +struct tcp_md5sig_info { + struct tcp4_md5sig_key *keys4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct tcp6_md5sig_key *keys6; + u32 entries6; + u32 alloced6; +#endif + u32 entries4; + u32 alloced4; +}; + +/* - pseudo header */ +struct tcp4_pseudohdr { + __be32 saddr; + __be32 daddr; + __u8 pad; + __u8 protocol; + __be16 len; +}; + +struct tcp6_pseudohdr { + struct in6_addr saddr; + struct in6_addr daddr; + __be32 len; + __be32 protocol; /* including padding */ +}; + +union tcp_md5sum_block { + struct tcp4_pseudohdr ip4; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + struct tcp6_pseudohdr ip6; +#endif +}; + +/* - pool: digest algorithm, hash description and scratch buffer */ +struct tcp_md5sig_pool { + struct hash_desc md5_desc; + union tcp_md5sum_block md5_blk; +}; + +#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */ + +/* - functions */ +extern int tcp_v4_calc_md5_hash(char *md5_hash, + struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, + int protocol, int tcplen); +extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, + struct sock *addr_sk); + +extern int tcp_v4_md5_do_add(struct sock *sk, + __be32 addr, + u8 *newkey, + u8 newkeylen); + +extern int tcp_v4_md5_do_del(struct sock *sk, + u32 addr); + +extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); +extern void tcp_free_md5sig_pool(void); + +extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); +extern void __tcp_put_md5sig_pool(void); + +static inline +struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) +{ + int cpu = get_cpu(); + struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu); + if (!ret) + put_cpu(); + return ret; +} + +static inline void tcp_put_md5sig_pool(void) +{ + __tcp_put_md5sig_pool(); + put_cpu(); +} + /* /proc */ enum tcp_seq_states { TCP_SEQ_STATE_LISTENING, @@ -1103,6 +1217,35 @@ extern int tcp4_proc_init(void); extern void tcp4_proc_exit(void); #endif +/* TCP af-specific functions */ +struct tcp_sock_af_ops { +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, + struct sock *addr_sk); + int (*calc_md5_hash) (char *location, + struct tcp_md5sig_key *md5, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, + int protocol, int len); + int (*md5_add) (struct sock *sk, + struct sock *addr_sk, + u8 *newkey, + u8 len); + int (*md5_parse) (struct sock *sk, + char __user *optval, + int optlen); +#endif +}; + +struct tcp_request_sock_ops { +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk, + struct request_sock *req); +#endif +}; + extern void tcp_v4_init(struct net_proto_family *ops); extern void tcp_init(void); diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h index be293d795e3..d7a306ea560 100644 --- a/include/net/timewait_sock.h +++ b/include/net/timewait_sock.h @@ -31,6 +31,9 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) static inline void twsk_destructor(struct sock *sk) { + BUG_ON(sk == NULL); + BUG_ON(sk->sk_prot == NULL); + BUG_ON(sk->sk_prot->twsk_prot == NULL); if (sk->sk_prot->twsk_prot->twsk_destructor != NULL) sk->sk_prot->twsk_prot->twsk_destructor(sk); } diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 34d6d197c3b..35985334dae 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -509,7 +509,7 @@ out: return err; } -static void dccp_v4_ctl_send_reset(struct sk_buff *rxskb) +static void dccp_v4_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) { int err; struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; @@ -724,7 +724,7 @@ int dccp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - dccp_v4_ctl_send_reset(skb); + dccp_v4_ctl_send_reset(sk, skb); discard: kfree_skb(skb); return 0; @@ -913,7 +913,7 @@ no_dccp_socket: if (dh->dccph_type != DCCP_PKT_RESET) { DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; - dccp_v4_ctl_send_reset(skb); + dccp_v4_ctl_send_reset(sk, skb); } discard_it: diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index fc326173c21..e0a0607862e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -310,7 +310,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } -static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb) +static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) { struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh; const u32 dccp_hdr_reset_len = sizeof(struct dccp_hdr) + @@ -805,7 +805,7 @@ static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - dccp_v6_ctl_send_reset(skb); + dccp_v6_ctl_send_reset(sk, skb); discard: if (opt_skb != NULL) __kfree_skb(opt_skb); @@ -902,7 +902,7 @@ no_dccp_socket: if (dh->dccph_type != DCCP_PKT_RESET) { DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION; - dccp_v6_ctl_send_reset(skb); + dccp_v6_ctl_send_reset(sk, skb); } discard_it: diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 0c49733f5be..3975048d809 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -246,7 +246,7 @@ listen_overflow: DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_TOO_BUSY; drop: if (dccp_hdr(skb)->dccph_type != DCCP_PKT_RESET) - req->rsk_ops->send_reset(skb); + req->rsk_ops->send_reset(sk, skb); inet_csk_reqsk_queue_drop(sk, req, prev); goto out; diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index bc298bcc344..39e0cb76358 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -618,5 +618,21 @@ config DEFAULT_TCP_CONG default "reno" if DEFAULT_RENO default "cubic" +config TCP_MD5SIG + bool "TCP: MD5 Signature Option support (RFC2385) (EXPERIMENTAL)" + depends on EXPERIMENTAL + select CRYPTO + select CRYPTO_MD5 + ---help--- + RFC2385 specifices a method of giving MD5 protection to TCP sessions. + Its main (only?) use is to protect BGP sessions between core routers + on the Internet. + + If unsure, say N. + +config TCP_MD5SIG_DEBUG + bool "TCP: MD5 Signature Option debugging" + depends on TCP_MD5SIG + source "net/ipv4/ipvs/Kconfig" diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index c05e8edaf54..dadef867a3b 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -258,6 +258,7 @@ #include #include #include +#include #include #include @@ -1942,6 +1943,13 @@ static int do_tcp_setsockopt(struct sock *sk, int level, } break; +#ifdef CONFIG_TCP_MD5SIG + case TCP_MD5SIG: + /* Read the IP->Key mappings from userspace */ + err = tp->af_specific->md5_parse(sk, optval, optlen); + break; +#endif + default: err = -ENOPROTOOPT; break; @@ -2231,6 +2239,135 @@ out: } EXPORT_SYMBOL(tcp_tso_segment); +#ifdef CONFIG_TCP_MD5SIG +static unsigned long tcp_md5sig_users; +static struct tcp_md5sig_pool **tcp_md5sig_pool; +static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); + +static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) +{ + int cpu; + for_each_possible_cpu(cpu) { + struct tcp_md5sig_pool *p = *per_cpu_ptr(pool, cpu); + if (p) { + if (p->md5_desc.tfm) + crypto_free_hash(p->md5_desc.tfm); + kfree(p); + p = NULL; + } + } + free_percpu(pool); +} + +void tcp_free_md5sig_pool(void) +{ + struct tcp_md5sig_pool **pool = NULL; + + spin_lock(&tcp_md5sig_pool_lock); + if (--tcp_md5sig_users == 0) { + pool = tcp_md5sig_pool; + tcp_md5sig_pool = NULL; + } + spin_unlock(&tcp_md5sig_pool_lock); + if (pool) + __tcp_free_md5sig_pool(pool); +} + +EXPORT_SYMBOL(tcp_free_md5sig_pool); + +struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) +{ + int cpu; + struct tcp_md5sig_pool **pool; + + pool = alloc_percpu(struct tcp_md5sig_pool *); + if (!pool) + return NULL; + + for_each_possible_cpu(cpu) { + struct tcp_md5sig_pool *p; + struct crypto_hash *hash; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + goto out_free; + *per_cpu_ptr(pool, cpu) = p; + + hash = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + if (!hash || IS_ERR(hash)) + goto out_free; + + p->md5_desc.tfm = hash; + } + return pool; +out_free: + __tcp_free_md5sig_pool(pool); + return NULL; +} + +struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void) +{ + struct tcp_md5sig_pool **pool; + int alloc = 0; + +retry: + spin_lock(&tcp_md5sig_pool_lock); + pool = tcp_md5sig_pool; + if (tcp_md5sig_users++ == 0) { + alloc = 1; + spin_unlock(&tcp_md5sig_pool_lock); + } else if (!pool) { + tcp_md5sig_users--; + spin_unlock(&tcp_md5sig_pool_lock); + cpu_relax(); + goto retry; + } else + spin_unlock(&tcp_md5sig_pool_lock); + + if (alloc) { + /* we cannot hold spinlock here because this may sleep. */ + struct tcp_md5sig_pool **p = __tcp_alloc_md5sig_pool(); + spin_lock(&tcp_md5sig_pool_lock); + if (!p) { + tcp_md5sig_users--; + spin_unlock(&tcp_md5sig_pool_lock); + return NULL; + } + pool = tcp_md5sig_pool; + if (pool) { + /* oops, it has already been assigned. */ + spin_unlock(&tcp_md5sig_pool_lock); + __tcp_free_md5sig_pool(p); + } else { + tcp_md5sig_pool = pool = p; + spin_unlock(&tcp_md5sig_pool_lock); + } + } + return pool; +} + +EXPORT_SYMBOL(tcp_alloc_md5sig_pool); + +struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu) +{ + struct tcp_md5sig_pool **p; + spin_lock(&tcp_md5sig_pool_lock); + p = tcp_md5sig_pool; + if (p) + tcp_md5sig_users++; + spin_unlock(&tcp_md5sig_pool_lock); + return (p ? *per_cpu_ptr(p, cpu) : NULL); +} + +EXPORT_SYMBOL(__tcp_get_md5sig_pool); + +void __tcp_put_md5sig_pool(void) { + __tcp_free_md5sig_pool(tcp_md5sig_pool); +} + +EXPORT_SYMBOL(__tcp_put_md5sig_pool); +#endif + extern void __skb_cb_too_small_for_tcp(int, int); extern struct tcp_congestion_ops tcp_reno; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4a8c96cdec7..6ab3423674b 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2677,6 +2677,14 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, opt_rx->sack_ok) { TCP_SKB_CB(skb)->sacked = (ptr - 2) - (unsigned char *)th; } +#ifdef CONFIG_TCP_MD5SIG + case TCPOPT_MD5SIG: + /* + * The MD5 Hash has already been + * checked (see tcp_v{4,6}_do_rcv()). + */ + break; +#endif }; ptr+=opsize-2; length-=opsize; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0ad0904bf56..8c8e8112f98 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -78,6 +78,9 @@ #include #include +#include +#include + int sysctl_tcp_tw_reuse __read_mostly; int sysctl_tcp_low_latency __read_mostly; @@ -89,6 +92,13 @@ static struct socket *tcp_socket; void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); +#ifdef CONFIG_TCP_MD5SIG +static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr); +static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + __be32 saddr, __be32 daddr, struct tcphdr *th, + int protocol, int tcplen); +#endif + struct inet_hashinfo __cacheline_aligned tcp_hashinfo = { .lhash_lock = __RW_LOCK_UNLOCKED(tcp_hashinfo.lhash_lock), .lhash_users = ATOMIC_INIT(0), @@ -526,11 +536,19 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) * Exception: precedence violation. We do not implement it in any case. */ -static void tcp_v4_send_reset(struct sk_buff *skb) +static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = skb->h.th; - struct tcphdr rth; + struct { + struct tcphdr th; +#ifdef CONFIG_TCP_MD5SIG + u32 opt[(TCPOLEN_MD5SIG_ALIGNED >> 2)]; +#endif + } rep; struct ip_reply_arg arg; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif /* Never send a reset in response to a reset. */ if (th->rst) @@ -540,29 +558,50 @@ static void tcp_v4_send_reset(struct sk_buff *skb) return; /* Swap the send and the receive. */ - memset(&rth, 0, sizeof(struct tcphdr)); - rth.dest = th->source; - rth.source = th->dest; - rth.doff = sizeof(struct tcphdr) / 4; - rth.rst = 1; + memset(&rep, 0, sizeof(rep)); + rep.th.dest = th->source; + rep.th.source = th->dest; + rep.th.doff = sizeof(struct tcphdr) / 4; + rep.th.rst = 1; if (th->ack) { - rth.seq = th->ack_seq; + rep.th.seq = th->ack_seq; } else { - rth.ack = 1; - rth.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + - skb->len - (th->doff << 2)); + rep.th.ack = 1; + rep.th.ack_seq = htonl(ntohl(th->seq) + th->syn + th->fin + + skb->len - (th->doff << 2)); } memset(&arg, 0, sizeof arg); - arg.iov[0].iov_base = (unsigned char *)&rth; - arg.iov[0].iov_len = sizeof rth; + arg.iov[0].iov_base = (unsigned char *)&rep; + arg.iov[0].iov_len = sizeof(rep.th); + +#ifdef CONFIG_TCP_MD5SIG + key = sk ? tcp_v4_md5_do_lookup(sk, skb->nh.iph->daddr) : NULL; + if (key) { + rep.opt[0] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + /* Update length and the length the header thinks exists */ + arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; + rep.th.doff = arg.iov[0].iov_len / 4; + + tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1], + key, + skb->nh.iph->daddr, + skb->nh.iph->saddr, + &rep.th, IPPROTO_TCP, + arg.iov[0].iov_len); + } +#endif + arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, skb->nh.iph->saddr, /*XXX*/ sizeof(struct tcphdr), IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr, check) / 2; - ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth); + ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); @@ -572,15 +611,24 @@ static void tcp_v4_send_reset(struct sk_buff *skb) outside socket context is ugly, certainly. What can I do? */ -static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, +static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, + struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) { struct tcphdr *th = skb->h.th; struct { struct tcphdr th; - u32 tsopt[TCPOLEN_TSTAMP_ALIGNED >> 2]; + u32 opt[(TCPOLEN_TSTAMP_ALIGNED >> 2) +#ifdef CONFIG_TCP_MD5SIG + + (TCPOLEN_MD5SIG_ALIGNED >> 2) +#endif + ]; } rep; struct ip_reply_arg arg; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; + struct tcp_md5sig_key tw_key; +#endif memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&arg, 0, sizeof arg); @@ -588,12 +636,12 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, arg.iov[0].iov_base = (unsigned char *)&rep; arg.iov[0].iov_len = sizeof(rep.th); if (ts) { - rep.tsopt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | - TCPOLEN_TIMESTAMP); - rep.tsopt[1] = htonl(tcp_time_stamp); - rep.tsopt[2] = htonl(ts); - arg.iov[0].iov_len = sizeof(rep); + rep.opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | + TCPOLEN_TIMESTAMP); + rep.opt[1] = htonl(tcp_time_stamp); + rep.opt[2] = htonl(ts); + arg.iov[0].iov_len = TCPOLEN_TSTAMP_ALIGNED; } /* Swap the send and the receive. */ @@ -605,6 +653,44 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, rep.th.ack = 1; rep.th.window = htons(win); +#ifdef CONFIG_TCP_MD5SIG + /* + * The SKB holds an imcoming packet, but may not have a valid ->sk + * pointer. This is especially the case when we're dealing with a + * TIME_WAIT ack, because the sk structure is long gone, and only + * the tcp_timewait_sock remains. So the md5 key is stashed in that + * structure, and we use it in preference. I believe that (twsk || + * skb->sk) holds true, but we program defensively. + */ + if (!twsk && skb->sk) { + key = tcp_v4_md5_do_lookup(skb->sk, skb->nh.iph->daddr); + } else if (twsk && twsk->tw_md5_keylen) { + tw_key.key = twsk->tw_md5_key; + tw_key.keylen = twsk->tw_md5_keylen; + key = &tw_key; + } else { + key = NULL; + } + + if (key) { + int offset = (ts) ? 3 : 0; + + rep.opt[offset++] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; + rep.th.doff = arg.iov[0].iov_len/4; + + tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset], + key, + skb->nh.iph->daddr, + skb->nh.iph->saddr, + &rep.th, IPPROTO_TCP, + arg.iov[0].iov_len); + } +#endif + arg.csum = csum_tcpudp_nofold(skb->nh.iph->daddr, skb->nh.iph->saddr, /*XXX*/ arg.iov[0].iov_len, IPPROTO_TCP, 0); @@ -618,9 +704,9 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) { struct inet_timewait_sock *tw = inet_twsk(sk); - const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); + struct tcp_timewait_sock *tcptw = tcp_twsk(sk); - tcp_v4_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, + tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); inet_twsk_put(tw); @@ -628,7 +714,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) { - tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, + tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, + tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); } @@ -714,6 +801,461 @@ static struct ip_options *tcp_v4_save_options(struct sock *sk, return dopt; } +#ifdef CONFIG_TCP_MD5SIG +/* + * RFC2385 MD5 checksumming requires a mapping of + * IP address->MD5 Key. + * We need to maintain these in the sk structure. + */ + +/* Find the Key structure for an address. */ +static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + if (!tp->md5sig_info || !tp->md5sig_info->entries4) + return NULL; + for (i = 0; i < tp->md5sig_info->entries4; i++) { + if (tp->md5sig_info->keys4[i].addr == addr) + return (struct tcp_md5sig_key *)&tp->md5sig_info->keys4[i]; + } + return NULL; +} + +struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, + struct sock *addr_sk) +{ + return tcp_v4_md5_do_lookup(sk, inet_sk(addr_sk)->daddr); +} + +EXPORT_SYMBOL(tcp_v4_md5_lookup); + +struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) +{ + return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); +} + +/* This can be called on a newly created socket, from other files */ +int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, + u8 *newkey, u8 newkeylen) +{ + /* Add Key to the list */ + struct tcp4_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + struct tcp4_md5sig_key *keys; + + key = (struct tcp4_md5sig_key *) tcp_v4_md5_do_lookup(sk, addr); + if (key) { + /* Pre-existing entry - just update that one. */ + kfree (key->key); + key->key = newkey; + key->keylen = newkeylen; + } else { + if (!tp->md5sig_info) { + tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); + if (!tp->md5sig_info) { + kfree(newkey); + return -ENOMEM; + } + } + if (tcp_alloc_md5sig_pool() == NULL) { + kfree(newkey); + return -ENOMEM; + } + if (tp->md5sig_info->alloced4 == tp->md5sig_info->entries4) { + keys = kmalloc((sizeof(struct tcp4_md5sig_key) * + (tp->md5sig_info->entries4 + 1)), GFP_ATOMIC); + if (!keys) { + kfree(newkey); + tcp_free_md5sig_pool(); + return -ENOMEM; + } + + if (tp->md5sig_info->entries4) + memcpy(keys, tp->md5sig_info->keys4, + (sizeof (struct tcp4_md5sig_key) * + tp->md5sig_info->entries4)); + + /* Free old key list, and reference new one */ + if (tp->md5sig_info->keys4) + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = keys; + tp->md5sig_info->alloced4++; + } + tp->md5sig_info->entries4++; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].addr = addr; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].key = newkey; + tp->md5sig_info->keys4[tp->md5sig_info->entries4 - 1].keylen = newkeylen; + } + return 0; +} + +EXPORT_SYMBOL(tcp_v4_md5_do_add); + +static int tcp_v4_md5_add_func(struct sock *sk, struct sock *addr_sk, + u8 *newkey, u8 newkeylen) +{ + return tcp_v4_md5_do_add(sk, inet_sk(addr_sk)->daddr, + newkey, newkeylen); +} + +int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + for (i = 0; i < tp->md5sig_info->entries4; i++) { + if (tp->md5sig_info->keys4[i].addr == addr) { + /* Free the key */ + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4--; + + if (tp->md5sig_info->entries4 == 0) { + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + } else { + /* Need to do some manipulation */ + if (tp->md5sig_info->entries4 != i) + memcpy(&tp->md5sig_info->keys4[i], + &tp->md5sig_info->keys4[i+1], + (tp->md5sig_info->entries4 - i) + * sizeof (struct tcp4_md5sig_key)); + } + tcp_free_md5sig_pool(); + return 0; + } + } + return -ENOENT; +} + +EXPORT_SYMBOL(tcp_v4_md5_do_del); + +static void tcp_v4_clear_md5_list (struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + + /* Free each key, then the set of key keys, + * the crypto element, and then decrement our + * hold on the last resort crypto. + */ + if (tp->md5sig_info->entries4) { + int i; + for (i = 0; i < tp->md5sig_info->entries4; i++) + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4 = 0; + tcp_free_md5sig_pool(); + } + if (tp->md5sig_info->keys4) { + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + tp->md5sig_info->alloced4 = 0; + } +} + +static int tcp_v4_parse_md5_keys (struct sock *sk, char __user *optval, + int optlen) +{ + struct tcp_md5sig cmd; + struct sockaddr_in *sin = (struct sockaddr_in *)&cmd.tcpm_addr; + u8 *newkey; + + if (optlen < sizeof(cmd)) + return -EINVAL; + + if (copy_from_user (&cmd, optval, sizeof(cmd))) + return -EFAULT; + + if (sin->sin_family != AF_INET) + return -EINVAL; + + if (!cmd.tcpm_key || !cmd.tcpm_keylen) { + if (!tcp_sk(sk)->md5sig_info) + return -ENOENT; + return tcp_v4_md5_do_del(sk, sin->sin_addr.s_addr); + } + + if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) + return -EINVAL; + + if (!tcp_sk(sk)->md5sig_info) { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_md5sig_info *p; + + p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); + if (!p) + return -EINVAL; + + tp->md5sig_info = p; + + } + + newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + if (!newkey) + return -ENOMEM; + memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); + return tcp_v4_md5_do_add(sk, sin->sin_addr.s_addr, + newkey, cmd.tcpm_keylen); +} + +static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + __be32 saddr, __be32 daddr, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct scatterlist sg[4]; + __u16 data_len; + int block = 0; +#ifdef CONFIG_TCP_MD5SIG_DEBUG + int i; +#endif + __u16 old_checksum; + struct tcp_md5sig_pool *hp; + struct tcp4_pseudohdr *bp; + struct hash_desc *desc; + int err; + unsigned int nbytes = 0; + + /* + * Okay, so RFC2385 is turned on for this connection, + * so we need to generate the MD5 hash for the packet now. + */ + + hp = tcp_get_md5sig_pool(); + if (!hp) + goto clear_hash_noput; + + bp = &hp->md5_blk.ip4; + desc = &hp->md5_desc; + + /* + * 1. the TCP pseudo-header (in the order: source IP address, + * destination IP address, zero-padded protocol number, and + * segment length) + */ + bp->saddr = saddr; + bp->daddr = daddr; + bp->pad = 0; + bp->protocol = protocol; + bp->len = htons(tcplen); + sg_set_buf(&sg[block++], bp, sizeof(*bp)); + nbytes += sizeof(*bp); + +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk("Calcuating hash for: "); + for (i = 0; i < sizeof (*bp); i++) + printk ("%02x ", (unsigned int)((unsigned char *)bp)[i]); + printk(" "); +#endif + + /* 2. the TCP header, excluding options, and assuming a + * checksum of zero/ + */ + old_checksum = th->check; + th->check = 0; + sg_set_buf(&sg[block++], th, sizeof(struct tcphdr)); + nbytes += sizeof(struct tcphdr); +#ifdef CONFIG_TCP_MD5SIG_DEBUG + for (i = 0; i < sizeof (struct tcphdr); i++) + printk (" %02x", (unsigned int)((unsigned char *)th)[i]); +#endif + /* 3. the TCP segment data (if any) */ + data_len = tcplen - (th->doff << 2); + if (data_len > 0) { + unsigned char *data = (unsigned char *)th + (th->doff << 2); + sg_set_buf(&sg[block++], data, data_len); + nbytes += data_len; + } + + /* 4. an independently-specified key or password, known to both + * TCPs and presumably connection-specific + */ + sg_set_buf(&sg[block++], key->key, key->keylen); + nbytes += key->keylen; + +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk (" and password: "); + for (i = 0; i < key->keylen; i++) + printk ("%02x ", (unsigned int)key->key[i]); +#endif + + /* Now store the Hash into the packet */ + err = crypto_hash_init(desc); + if (err) + goto clear_hash; + err = crypto_hash_update(desc, sg, nbytes); + if (err) + goto clear_hash; + err = crypto_hash_final(desc, md5_hash); + if (err) + goto clear_hash; + + /* Reset header, and free up the crypto */ + tcp_put_md5sig_pool(); + th->check = old_checksum; + +out: +#ifdef CONFIG_TCP_MD5SIG_DEBUG + printk(" result:"); + for (i = 0; i < 16; i++) + printk (" %02x", (unsigned int)(((u8*)md5_hash)[i])); + printk("\n"); +#endif + return 0; +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + goto out; +} + +int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, int protocol, + int tcplen) +{ + __be32 saddr, daddr; + + if (sk) { + saddr = inet_sk(sk)->saddr; + daddr = inet_sk(sk)->daddr; + } else { + struct rtable *rt = (struct rtable *)dst; + BUG_ON(!rt); + saddr = rt->rt_src; + daddr = rt->rt_dst; + } + return tcp_v4_do_calc_md5_hash(md5_hash, key, + saddr, daddr, + th, protocol, tcplen); +} + +EXPORT_SYMBOL(tcp_v4_calc_md5_hash); + +static int tcp_v4_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) +{ + /* + * This gets called for each TCP segment that arrives + * so we want to be efficient. + * We have 3 drop cases: + * o No MD5 hash and one expected. + * o MD5 hash and we're not expecting one. + * o MD5 hash and its wrong. + */ + __u8 *hash_location = NULL; + struct tcp_md5sig_key *hash_expected; + struct iphdr *iph = skb->nh.iph; + struct tcphdr *th = skb->h.th; + int length = (th->doff << 2) - sizeof (struct tcphdr); + int genhash; + unsigned char *ptr; + unsigned char newhash[16]; + + hash_expected = tcp_v4_md5_do_lookup(sk, iph->saddr); + + /* + * If the TCP option length is less than the TCP_MD5SIG + * option length, then we can shortcut + */ + if (length < TCPOLEN_MD5SIG) { + if (hash_expected) + return 1; + else + return 0; + } + + /* Okay, we can't shortcut - we have to grub through the options */ + ptr = (unsigned char *)(th + 1); + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCPOPT_EOL: + goto done_opts; + case TCPOPT_NOP: + length--; + continue; + default: + opsize = *ptr++; + if (opsize < 2) + goto done_opts; + if (opsize > length) + goto done_opts; + + if (opcode == TCPOPT_MD5SIG) { + hash_location = ptr; + goto done_opts; + } + } + ptr += opsize-2; + length -= opsize; + } +done_opts: + /* We've parsed the options - do we have a hash? */ + if (!hash_expected && !hash_location) + return 0; + + if (hash_expected && !hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest)); + } + return 1; + } + + if (!hash_expected && hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest)); + } + return 1; + } + + /* Okay, so this is hash_expected and hash_location - + * so we need to calculate the checksum. + */ + genhash = tcp_v4_do_calc_md5_hash(newhash, + hash_expected, + iph->saddr, iph->daddr, + th, sk->sk_protocol, + skb->len); + + if (genhash || memcmp(hash_location, newhash, 16) != 0) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash failed for " + "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)%s\n", + NIPQUAD (iph->saddr), ntohs(th->source), + NIPQUAD (iph->daddr), ntohs(th->dest), + genhash ? " tcp_v4_calc_md5_hash failed" : ""); +#ifdef CONFIG_TCP_MD5SIG_DEBUG + do { + int i; + printk("Received: "); + for (i = 0; i < 16; i++) + printk("%02x ", 0xff & (int)hash_location[i]); + printk("\n"); + printk("Calculated: "); + for (i = 0; i < 16; i++) + printk("%02x ", 0xff & (int)newhash[i]); + printk("\n"); + } while(0); +#endif + } + return 1; + } + return 0; +} + +#endif + struct request_sock_ops tcp_request_sock_ops __read_mostly = { .family = PF_INET, .obj_size = sizeof(struct tcp_request_sock), @@ -723,9 +1265,16 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; +struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_reqsk_md5_lookup, +#endif +}; + static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp_timewait_sock), .twsk_unique = tcp_twsk_unique, + .twsk_destructor= tcp_twsk_destructor, }; int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) @@ -773,6 +1322,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) if (!req) goto drop; +#ifdef CONFIG_TCP_MD5SIG + tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; +#endif + tcp_clear_options(&tmp_opt); tmp_opt.mss_clamp = 536; tmp_opt.user_mss = tcp_sk(sk)->rx_opt.user_mss; @@ -891,6 +1444,9 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct inet_sock *newinet; struct tcp_sock *newtp; struct sock *newsk; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (sk_acceptq_is_full(sk)) goto exit_overflow; @@ -925,6 +1481,24 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newtp->advmss = dst_metric(dst, RTAX_ADVMSS); tcp_initialize_rcv_mss(newsk); +#ifdef CONFIG_TCP_MD5SIG + /* Copy over the MD5 key from the original socket */ + if ((key = tcp_v4_md5_do_lookup(sk, newinet->daddr)) != NULL) { + /* + * We're using one, so create a matching key + * on the newsk structure. If we fail to get + * memory, then we end up not copying the key + * across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + memcpy(newkey, key->key, key->keylen); + tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, + newkey, key->keylen); + } + } +#endif + __inet_hash(&tcp_hashinfo, newsk, 0); __inet_inherit_port(&tcp_hashinfo, sk, newsk); @@ -1000,10 +1574,24 @@ static int tcp_v4_checksum_init(struct sk_buff *skb) */ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) { + struct sock *rsk; +#ifdef CONFIG_TCP_MD5SIG + /* + * We really want to reject the packet as early as possible + * if: + * o We're expecting an MD5'd packet and this is no MD5 tcp option + * o There is an MD5 option and we're not expecting one + */ + if (tcp_v4_inbound_md5_hash (sk, skb)) + goto discard; +#endif + if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ TCP_CHECK_TIMER(sk); - if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) + if (tcp_rcv_established(sk, skb, skb->h.th, skb->len)) { + rsk = sk; goto reset; + } TCP_CHECK_TIMER(sk); return 0; } @@ -1017,20 +1605,24 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) goto discard; if (nsk != sk) { - if (tcp_child_process(sk, nsk, skb)) + if (tcp_child_process(sk, nsk, skb)) { + rsk = nsk; goto reset; + } return 0; } } TCP_CHECK_TIMER(sk); - if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) + if (tcp_rcv_state_process(sk, skb, skb->h.th, skb->len)) { + rsk = sk; goto reset; + } TCP_CHECK_TIMER(sk); return 0; reset: - tcp_v4_send_reset(skb); + tcp_v4_send_reset(rsk, skb); discard: kfree_skb(skb); /* Be careful here. If this function gets more complicated and @@ -1139,7 +1731,7 @@ no_tcp_socket: bad_packet: TCP_INC_STATS_BH(TCP_MIB_INERRS); } else { - tcp_v4_send_reset(skb); + tcp_v4_send_reset(NULL, skb); } discard_it: @@ -1262,6 +1854,15 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; +struct tcp_sock_af_ops tcp_sock_ipv4_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_md5_lookup, + .calc_md5_hash = tcp_v4_calc_md5_hash, + .md5_add = tcp_v4_md5_add_func, + .md5_parse = tcp_v4_parse_md5_keys, +#endif +}; + /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. */ @@ -1301,6 +1902,9 @@ static int tcp_v4_init_sock(struct sock *sk) icsk->icsk_af_ops = &ipv4_specific; icsk->icsk_sync_mss = tcp_sync_mss; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv4_specific; +#endif sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; @@ -1324,6 +1928,15 @@ int tcp_v4_destroy_sock(struct sock *sk) /* Cleans up our, hopefully empty, out_of_order_queue. */ __skb_queue_purge(&tp->out_of_order_queue); +#ifdef CONFIG_TCP_MD5SIG + /* Clean up the MD5 key list, if any */ + if (tp->md5sig_info) { + tcp_v4_clear_md5_list(sk); + kfree(tp->md5sig_info); + tp->md5sig_info = NULL; + } +#endif + #ifdef CONFIG_NET_DMA /* Cleans up our sk_async_wait_queue */ __skb_queue_purge(&sk->sk_async_wait_queue); diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0163d982690..ac55d8892cf 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -306,6 +306,28 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) tw->tw_ipv6only = np->ipv6only; } #endif + +#ifdef CONFIG_TCP_MD5SIG + /* + * The timewait bucket does not have the key DB from the + * sock structure. We just make a quick copy of the + * md5 key being used (if indeed we are using one) + * so the timewait ack generating code has the key. + */ + do { + struct tcp_md5sig_key *key; + memset(tcptw->tw_md5_key, 0, sizeof(tcptw->tw_md5_key)); + tcptw->tw_md5_keylen = 0; + key = tp->af_specific->md5_lookup(sk, sk); + if (key != NULL) { + memcpy(&tcptw->tw_md5_key, key->key, key->keylen); + tcptw->tw_md5_keylen = key->keylen; + if (tcp_alloc_md5sig_pool() == NULL) + BUG(); + } + } while(0); +#endif + /* Linkage updates. */ __inet_twsk_hashdance(tw, sk, &tcp_hashinfo); @@ -337,6 +359,17 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) tcp_done(sk); } +void tcp_twsk_destructor(struct sock *sk) +{ + struct tcp_timewait_sock *twsk = tcp_twsk(sk); +#ifdef CONFIG_TCP_MD5SIG + if (twsk->tw_md5_keylen) + tcp_put_md5sig_pool(); +#endif +} + +EXPORT_SYMBOL_GPL(tcp_twsk_destructor); + /* This is not only more efficient than what we used to do, it eliminates * a lot of code duplication between IPv4/IPv6 SYN recv processing. -DaveM * @@ -435,6 +468,11 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, newtp->rx_opt.ts_recent_stamp = 0; newtp->tcp_header_len = sizeof(struct tcphdr); } +#ifdef CONFIG_TCP_MD5SIG + newtp->md5sig_info = NULL; /*XXX*/ + if (newtp->af_specific->md5_lookup(sk, newsk)) + newtp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; +#endif if (skb->len >= TCP_MIN_RCVMSS+newtp->tcp_header_len) newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newtp->rx_opt.mss_clamp = req->mss; @@ -617,6 +655,30 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, req, NULL); if (child == NULL) goto listen_overflow; +#ifdef CONFIG_TCP_MD5SIG + else { + /* Copy over the MD5 key from the original socket */ + struct tcp_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + key = tp->af_specific->md5_lookup(sk, child); + if (key != NULL) { + /* + * We're using one, so create a matching key on the + * newsk structure. If we fail to get memory then we + * end up not copying the key across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + if (!tcp_alloc_md5sig_pool()) + BUG(); + memcpy(newkey, key->key, key->keylen); + tp->af_specific->md5_add(child, child, + newkey, + key->keylen); + } + } + } +#endif inet_csk_reqsk_queue_unlink(sk, req, prev); inet_csk_reqsk_queue_removed(sk, req); @@ -633,7 +695,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, embryonic_reset: NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS); if (!(flg & TCP_FLAG_RST)) - req->rsk_ops->send_reset(skb); + req->rsk_ops->send_reset(sk, skb); inet_csk_reqsk_queue_drop(sk, req, prev); return NULL; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6a8581ab9a2..32c1a972fa3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -270,7 +270,7 @@ static u16 tcp_select_window(struct sock *sk) } static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, - __u32 tstamp) + __u32 tstamp, __u8 **md5_hash) { if (tp->rx_opt.tstamp_ok) { *ptr++ = htonl((TCPOPT_NOP << 24) | @@ -298,16 +298,29 @@ static void tcp_build_and_update_options(__be32 *ptr, struct tcp_sock *tp, tp->rx_opt.eff_sacks--; } } +#ifdef CONFIG_TCP_MD5SIG + if (md5_hash) { + *ptr++ = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + *md5_hash = (__u8 *)ptr; + } +#endif } /* Construct a tcp options header for a SYN or SYN_ACK packet. * If this is every changed make sure to change the definition of * MAX_SYN_SIZE to match the new maximum number of options that you * can generate. + * + * Note - that with the RFC2385 TCP option, we make room for the + * 16 byte MD5 hash. This will be filled in later, so the pointer for the + * location to be filled is passed back up. */ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, int offer_wscale, int wscale, __u32 tstamp, - __u32 ts_recent) + __u32 ts_recent, __u8 **md5_hash) { /* We always get an MSS option. * The option bytes which will be seen in normal data @@ -346,6 +359,20 @@ static void tcp_syn_build_options(__be32 *ptr, int mss, int ts, int sack, (TCPOPT_WINDOW << 16) | (TCPOLEN_WINDOW << 8) | (wscale)); +#ifdef CONFIG_TCP_MD5SIG + /* + * If MD5 is enabled, then we set the option, and include the size + * (always 18). The actual MD5 hash is added just before the + * packet is sent. + */ + if (md5_hash) { + *ptr++ = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + *md5_hash = (__u8 *) ptr; + } +#endif } /* This routine actually transmits TCP packets queued in by @@ -366,6 +393,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, struct tcp_sock *tp; struct tcp_skb_cb *tcb; int tcp_header_size; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *md5; + __u8 *md5_hash_location; +#endif struct tcphdr *th; int sysctl_flags; int err; @@ -424,6 +455,16 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, if (tcp_packets_in_flight(tp) == 0) tcp_ca_event(sk, CA_EVENT_TX_START); +#ifdef CONFIG_TCP_MD5SIG + /* + * Are we doing MD5 on this segment? If so - make + * room for it. + */ + md5 = tp->af_specific->md5_lookup(sk, sk); + if (md5) + tcp_header_size += TCPOLEN_MD5SIG_ALIGNED; +#endif + th = (struct tcphdr *) skb_push(skb, tcp_header_size); skb->h.th = th; @@ -460,13 +501,34 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, (sysctl_flags & SYSCTL_FLAG_WSCALE), tp->rx_opt.rcv_wscale, tcb->when, - tp->rx_opt.ts_recent); + tp->rx_opt.ts_recent, + +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL); } else { tcp_build_and_update_options((__be32 *)(th + 1), - tp, tcb->when); + tp, tcb->when, +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL); TCP_ECN_send(sk, tp, skb, tcp_header_size); } +#ifdef CONFIG_TCP_MD5SIG + /* Calculate the MD5 hash, as we have all we need now */ + if (md5) { + tp->af_specific->calc_md5_hash(md5_hash_location, + md5, + sk, NULL, NULL, + skb->h.th, + sk->sk_protocol, + skb->len); + } +#endif + icsk->icsk_af_ops->send_check(sk, skb->len, skb); if (likely(tcb->flags & TCPCB_FLAG_ACK)) @@ -840,6 +902,11 @@ unsigned int tcp_current_mss(struct sock *sk, int large_allowed) mss_now -= (TCPOLEN_SACK_BASE_ALIGNED + (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK)); +#ifdef CONFIG_TCP_MD5SIG + if (tp->af_specific->md5_lookup(sk, sk)) + mss_now -= TCPOLEN_MD5SIG_ALIGNED; +#endif + xmit_size_goal = mss_now; if (doing_tso) { @@ -2033,6 +2100,10 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct tcphdr *th; int tcp_header_size; struct sk_buff *skb; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *md5; + __u8 *md5_hash_location; +#endif skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); if (skb == NULL) @@ -2048,6 +2119,13 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) + /* SACK_PERM is in the place of NOP NOP of TS */ ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0)); + +#ifdef CONFIG_TCP_MD5SIG + /* Are we doing MD5 on this segment? If so - make room for it */ + md5 = tcp_rsk(req)->af_specific->md5_lookup(sk, req); + if (md5) + tcp_header_size += TCPOLEN_MD5SIG_ALIGNED; +#endif skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size); memset(th, 0, sizeof(struct tcphdr)); @@ -2085,11 +2163,29 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok, ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale, TCP_SKB_CB(skb)->when, - req->ts_recent); + req->ts_recent, + ( +#ifdef CONFIG_TCP_MD5SIG + md5 ? &md5_hash_location : +#endif + NULL) + ); skb->csum = 0; th->doff = (tcp_header_size >> 2); TCP_INC_STATS(TCP_MIB_OUTSEGS); + +#ifdef CONFIG_TCP_MD5SIG + /* Okay, we have all we need - do the md5 hash if needed */ + if (md5) { + tp->af_specific->calc_md5_hash(md5_hash_location, + md5, + NULL, dst, req, + skb->h.th, sk->sk_protocol, + skb->len); + } +#endif + return skb; } @@ -2108,6 +2204,11 @@ static void tcp_connect_init(struct sock *sk) tp->tcp_header_len = sizeof(struct tcphdr) + (sysctl_tcp_timestamps ? TCPOLEN_TSTAMP_ALIGNED : 0); +#ifdef CONFIG_TCP_MD5SIG + if (tp->af_specific->md5_lookup(sk, sk) != NULL) + tp->tcp_header_len += TCPOLEN_MD5SIG_ALIGNED; +#endif + /* If user gave his TCP_MAXSEG, record it to clamp */ if (tp->rx_opt.user_mss) tp->rx_opt.mss_clamp = tp->rx_opt.user_mss; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9a88395a762..663d1d23801 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -66,10 +66,13 @@ #include #include +#include +#include + /* Socket used for sending RSTs and ACKs */ static struct socket *tcp6_socket; -static void tcp_v6_send_reset(struct sk_buff *skb); +static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb); @@ -78,6 +81,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); static struct inet_connection_sock_af_ops ipv6_mapped; static struct inet_connection_sock_af_ops ipv6_specific; +static struct tcp_sock_af_ops tcp_sock_ipv6_specific; +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; static int tcp_v6_get_port(struct sock *sk, unsigned short snum) { @@ -208,6 +213,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_af_ops = &ipv6_mapped; sk->sk_backlog_rcv = tcp_v4_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_mapped_specific; +#endif err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin)); @@ -215,6 +223,9 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, icsk->icsk_ext_hdr_len = exthdrlen; icsk->icsk_af_ops = &ipv6_specific; sk->sk_backlog_rcv = tcp_v6_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_specific; +#endif goto failure; } else { ipv6_addr_set(&np->saddr, 0, 0, htonl(0x0000FFFF), @@ -518,6 +529,396 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) kfree_skb(inet6_rsk(req)->pktopts); } +#ifdef CONFIG_TCP_MD5SIG +static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, + struct in6_addr *addr) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + BUG_ON(tp == NULL); + + if (!tp->md5sig_info || !tp->md5sig_info->entries6) + return NULL; + + for (i = 0; i < tp->md5sig_info->entries6; i++) { + if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) + return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; + } + return NULL; +} + +static struct tcp_md5sig_key *tcp_v6_md5_lookup(struct sock *sk, + struct sock *addr_sk) +{ + return tcp_v6_md5_do_lookup(sk, &inet6_sk(addr_sk)->daddr); +} + +static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) +{ + return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); +} + +static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, + char *newkey, u8 newkeylen) +{ + /* Add key to the list */ + struct tcp6_md5sig_key *key; + struct tcp_sock *tp = tcp_sk(sk); + struct tcp6_md5sig_key *keys; + + key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); + if (key) { + /* modify existing entry - just update that one */ + kfree(key->key); + key->key = newkey; + key->keylen = newkeylen; + } else { + /* reallocate new list if current one is full. */ + if (!tp->md5sig_info) { + tp->md5sig_info = kzalloc(sizeof(*tp->md5sig_info), GFP_ATOMIC); + if (!tp->md5sig_info) { + kfree(newkey); + return -ENOMEM; + } + } + tcp_alloc_md5sig_pool(); + if (tp->md5sig_info->alloced6 == tp->md5sig_info->entries6) { + keys = kmalloc((sizeof (tp->md5sig_info->keys6[0]) * + (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); + + if (!keys) { + tcp_free_md5sig_pool(); + kfree(newkey); + return -ENOMEM; + } + + if (tp->md5sig_info->entries6) + memmove(keys, tp->md5sig_info->keys6, + (sizeof (tp->md5sig_info->keys6[0]) * + tp->md5sig_info->entries6)); + + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = keys; + tp->md5sig_info->alloced6++; + } + + ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, + peer); + tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; + tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; + + tp->md5sig_info->entries6++; + } + return 0; +} + +static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, + u8 *newkey, __u8 newkeylen) +{ + return tcp_v6_md5_do_add(sk, &inet6_sk(addr_sk)->daddr, + newkey, newkeylen); +} + +static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + for (i = 0; i < tp->md5sig_info->entries6; i++) { + if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { + /* Free the key */ + kfree(tp->md5sig_info->keys6[i].key); + tp->md5sig_info->entries6--; + + if (tp->md5sig_info->entries6 == 0) { + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = NULL; + + tcp_free_md5sig_pool(); + + return 0; + } else { + /* shrink the database */ + if (tp->md5sig_info->entries6 != i) + memmove(&tp->md5sig_info->keys6[i], + &tp->md5sig_info->keys6[i+1], + (tp->md5sig_info->entries6 - i) + * sizeof (tp->md5sig_info->keys6[0])); + } + } + } + return -ENOENT; +} + +static void tcp_v6_clear_md5_list (struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + int i; + + if (tp->md5sig_info->entries6) { + for (i = 0; i < tp->md5sig_info->entries6; i++) + kfree(tp->md5sig_info->keys6[i].key); + tp->md5sig_info->entries6 = 0; + tcp_free_md5sig_pool(); + } + + kfree(tp->md5sig_info->keys6); + tp->md5sig_info->keys6 = NULL; + tp->md5sig_info->alloced6 = 0; + + if (tp->md5sig_info->entries4) { + for (i = 0; i < tp->md5sig_info->entries4; i++) + kfree(tp->md5sig_info->keys4[i].key); + tp->md5sig_info->entries4 = 0; + tcp_free_md5sig_pool(); + } + + kfree(tp->md5sig_info->keys4); + tp->md5sig_info->keys4 = NULL; + tp->md5sig_info->alloced4 = 0; +} + +static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, + int optlen) +{ + struct tcp_md5sig cmd; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; + u8 *newkey; + + if (optlen < sizeof(cmd)) + return -EINVAL; + + if (copy_from_user(&cmd, optval, sizeof(cmd))) + return -EFAULT; + + if (sin6->sin6_family != AF_INET6) + return -EINVAL; + + if (!cmd.tcpm_keylen) { + if (!tcp_sk(sk)->md5sig_info) + return -ENOENT; + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) + return tcp_v4_md5_do_del(sk, sin6->sin6_addr.s6_addr32[3]); + return tcp_v6_md5_do_del(sk, &sin6->sin6_addr); + } + + if (cmd.tcpm_keylen > TCP_MD5SIG_MAXKEYLEN) + return -EINVAL; + + if (!tcp_sk(sk)->md5sig_info) { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_md5sig_info *p; + + p = kzalloc(sizeof(struct tcp_md5sig_info), GFP_KERNEL); + if (!p) + return -ENOMEM; + + tp->md5sig_info = p; + } + + newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + if (!newkey) + return -ENOMEM; + memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { + return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], + newkey, cmd.tcpm_keylen); + } + return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); +} + +static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct in6_addr *saddr, + struct in6_addr *daddr, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct scatterlist sg[4]; + __u16 data_len; + int block = 0; + __u16 cksum; + struct tcp_md5sig_pool *hp; + struct tcp6_pseudohdr *bp; + struct hash_desc *desc; + int err; + unsigned int nbytes = 0; + + hp = tcp_get_md5sig_pool(); + if (!hp) { + printk(KERN_WARNING "%s(): hash pool not found...\n", __FUNCTION__); + goto clear_hash_noput; + } + bp = &hp->md5_blk.ip6; + desc = &hp->md5_desc; + + /* 1. TCP pseudo-header (RFC2460) */ + ipv6_addr_copy(&bp->saddr, saddr); + ipv6_addr_copy(&bp->daddr, daddr); + bp->len = htonl(tcplen); + bp->protocol = htonl(protocol); + + sg_set_buf(&sg[block++], bp, sizeof(*bp)); + nbytes += sizeof(*bp); + + /* 2. TCP header, excluding options */ + cksum = th->check; + th->check = 0; + sg_set_buf(&sg[block++], th, sizeof(*th)); + nbytes += sizeof(*th); + + /* 3. TCP segment data (if any) */ + data_len = tcplen - (th->doff << 2); + if (data_len > 0) { + u8 *data = (u8 *)th + (th->doff << 2); + sg_set_buf(&sg[block++], data, data_len); + nbytes += data_len; + } + + /* 4. shared key */ + sg_set_buf(&sg[block++], key->key, key->keylen); + nbytes += key->keylen; + + /* Now store the hash into the packet */ + err = crypto_hash_init(desc); + if (err) { + printk(KERN_WARNING "%s(): hash_init failed\n", __FUNCTION__); + goto clear_hash; + } + err = crypto_hash_update(desc, sg, nbytes); + if (err) { + printk(KERN_WARNING "%s(): hash_update failed\n", __FUNCTION__); + goto clear_hash; + } + err = crypto_hash_final(desc, md5_hash); + if (err) { + printk(KERN_WARNING "%s(): hash_final failed\n", __FUNCTION__); + goto clear_hash; + } + + /* Reset header, and free up the crypto */ + tcp_put_md5sig_pool(); + th->check = cksum; +out: + return 0; +clear_hash: + tcp_put_md5sig_pool(); +clear_hash_noput: + memset(md5_hash, 0, 16); + goto out; +} + +static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, + struct sock *sk, + struct dst_entry *dst, + struct request_sock *req, + struct tcphdr *th, int protocol, + int tcplen) +{ + struct in6_addr *saddr, *daddr; + + if (sk) { + saddr = &inet6_sk(sk)->saddr; + daddr = &inet6_sk(sk)->daddr; + } else { + saddr = &inet6_rsk(req)->loc_addr; + daddr = &inet6_rsk(req)->rmt_addr; + } + return tcp_v6_do_calc_md5_hash(md5_hash, key, + saddr, daddr, + th, protocol, tcplen); +} + +static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) +{ + __u8 *hash_location = NULL; + struct tcp_md5sig_key *hash_expected; + struct ipv6hdr *ip6h = skb->nh.ipv6h; + struct tcphdr *th = skb->h.th; + int length = (th->doff << 2) - sizeof (*th); + int genhash; + u8 *ptr; + u8 newhash[16]; + + hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); + + /* If the TCP option is too short, we can short cut */ + if (length < TCPOLEN_MD5SIG) + return hash_expected ? 1 : 0; + + /* parse options */ + ptr = (u8*)(th + 1); + while (length > 0) { + int opcode = *ptr++; + int opsize; + + switch(opcode) { + case TCPOPT_EOL: + goto done_opts; + case TCPOPT_NOP: + length--; + continue; + default: + opsize = *ptr++; + if (opsize < 2 || opsize > length) + goto done_opts; + if (opcode == TCPOPT_MD5SIG) { + hash_location = ptr; + goto done_opts; + } + } + ptr += opsize - 2; + length -= opsize; + } + +done_opts: + /* do we have a hash as expected? */ + if (!hash_expected) { + if (!hash_location) + return 0; + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash NOT expected but found " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + + if (!hash_location) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash expected but NOT found " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + + /* check the signature */ + genhash = tcp_v6_do_calc_md5_hash(newhash, + hash_expected, + &ip6h->saddr, &ip6h->daddr, + th, sk->sk_protocol, + skb->len); + if (genhash || memcmp(hash_location, newhash, 16) != 0) { + if (net_ratelimit()) { + printk(KERN_INFO "MD5 Hash %s for " + "(" NIP6_FMT ", %u)->" + "(" NIP6_FMT ", %u)\n", + genhash ? "failed" : "mismatch", + NIP6(ip6h->saddr), ntohs(th->source), + NIP6(ip6h->daddr), ntohs(th->dest)); + } + return 1; + } + return 0; +} +#endif + static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .family = AF_INET6, .obj_size = sizeof(struct tcp6_request_sock), @@ -527,9 +928,16 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; +struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v6_reqsk_md5_lookup, +#endif +}; + static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp6_timewait_sock), .twsk_unique = tcp_twsk_unique, + .twsk_destructor= tcp_twsk_destructor, }; static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) @@ -566,11 +974,15 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) return 0; } -static void tcp_v6_send_reset(struct sk_buff *skb) +static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) { struct tcphdr *th = skb->h.th, *t1; struct sk_buff *buff; struct flowi fl; + int tot_len = sizeof(*th); +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (th->rst) return; @@ -578,25 +990,35 @@ static void tcp_v6_send_reset(struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) return; +#ifdef CONFIG_TCP_MD5SIG + if (sk) + key = tcp_v6_md5_do_lookup(sk, &skb->nh.ipv6h->daddr); + else + key = NULL; + + if (key) + tot_len += TCPOLEN_MD5SIG_ALIGNED; +#endif + /* * We need to grab some memory, and put together an RST, * and then put it into the queue to be sent. */ - buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr), + buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); if (buff == NULL) return; - skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + sizeof(struct tcphdr)); + skb_reserve(buff, MAX_HEADER + sizeof(struct ipv6hdr) + tot_len); - t1 = (struct tcphdr *) skb_push(buff,sizeof(struct tcphdr)); + t1 = (struct tcphdr *) skb_push(buff, tot_len); /* Swap the send and the receive. */ memset(t1, 0, sizeof(*t1)); t1->dest = th->source; t1->source = th->dest; - t1->doff = sizeof(*t1)/4; + t1->doff = tot_len / 4; t1->rst = 1; if(th->ack) { @@ -607,6 +1029,22 @@ static void tcp_v6_send_reset(struct sk_buff *skb) + skb->len - (th->doff<<2)); } +#ifdef CONFIG_TCP_MD5SIG + if (key) { + u32 *opt = (u32*)(t1 + 1); + opt[0] = htonl((TCPOPT_NOP << 24) | + (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | + TCPOLEN_MD5SIG); + tcp_v6_do_calc_md5_hash((__u8*)&opt[1], + key, + &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr, + t1, IPPROTO_TCP, + tot_len); + } +#endif + buff->csum = csum_partial((char *)t1, sizeof(*t1), 0); memset(&fl, 0, sizeof(fl)); @@ -637,15 +1075,37 @@ static void tcp_v6_send_reset(struct sk_buff *skb) kfree_skb(buff); } -static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) +static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, + struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) { struct tcphdr *th = skb->h.th, *t1; struct sk_buff *buff; struct flowi fl; int tot_len = sizeof(struct tcphdr); + u32 *topt; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; + struct tcp_md5sig_key tw_key; +#endif + +#ifdef CONFIG_TCP_MD5SIG + if (!tw && skb->sk) { + key = tcp_v6_md5_do_lookup(skb->sk, &skb->nh.ipv6h->daddr); + } else if (tw && tw->tw_md5_keylen) { + tw_key.key = tw->tw_md5_key; + tw_key.keylen = tw->tw_md5_keylen; + key = &tw_key; + } else { + key = NULL; + } +#endif if (ts) tot_len += TCPOLEN_TSTAMP_ALIGNED; +#ifdef CONFIG_TCP_MD5SIG + if (key) + tot_len += TCPOLEN_MD5SIG_ALIGNED; +#endif buff = alloc_skb(MAX_HEADER + sizeof(struct ipv6hdr) + tot_len, GFP_ATOMIC); @@ -665,15 +1125,29 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 t1->ack_seq = htonl(ack); t1->ack = 1; t1->window = htons(win); + + topt = (u32*)(t1 + 1); if (ts) { - u32 *ptr = (u32*)(t1 + 1); - *ptr++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | - (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); - *ptr++ = htonl(tcp_time_stamp); - *ptr = htonl(ts); + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP); + *topt++ = htonl(tcp_time_stamp); + *topt = htonl(ts); } +#ifdef CONFIG_TCP_MD5SIG + if (key) { + *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); + tcp_v6_do_calc_md5_hash((__u8 *)topt, + key, + &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr, + t1, IPPROTO_TCP, + tot_len); + } +#endif + buff->csum = csum_partial((char *)t1, tot_len, 0); memset(&fl, 0, sizeof(fl)); @@ -704,9 +1178,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) { struct inet_timewait_sock *tw = inet_twsk(sk); - const struct tcp_timewait_sock *tcptw = tcp_twsk(sk); + struct tcp_timewait_sock *tcptw = tcp_twsk(sk); - tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, + tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, tcptw->tw_ts_recent); @@ -715,7 +1189,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) { - tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); + tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); } @@ -786,6 +1260,10 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (req == NULL) goto drop; +#ifdef CONFIG_TCP_MD5SIG + tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; +#endif + tcp_clear_options(&tmp_opt); tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); tmp_opt.user_mss = tp->rx_opt.user_mss; @@ -844,6 +1322,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, struct tcp_sock *newtp; struct sock *newsk; struct ipv6_txoptions *opt; +#ifdef CONFIG_TCP_MD5SIG + struct tcp_md5sig_key *key; +#endif if (skb->protocol == htons(ETH_P_IP)) { /* @@ -874,6 +1355,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_af_ops = &ipv6_mapped; newsk->sk_backlog_rcv = tcp_v4_do_rcv; +#ifdef CONFIG_TCP_MD5SIG + newtp->af_specific = &tcp_sock_ipv6_mapped_specific; +#endif + newnp->pktoptions = NULL; newnp->opt = NULL; newnp->mcast_oif = inet6_iif(skb); @@ -1008,6 +1493,23 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6; +#ifdef CONFIG_TCP_MD5SIG + /* Copy over the MD5 key from the original socket */ + if ((key = tcp_v6_md5_do_lookup(sk, &newnp->daddr)) != NULL) { + /* We're using one, so create a matching key + * on the newsk structure. If we fail to get + * memory, then we end up not copying the key + * across. Shucks. + */ + char *newkey = kmalloc(key->keylen, GFP_ATOMIC); + if (newkey) { + memcpy(newkey, key->key, key->keylen); + tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, + newkey, key->keylen); + } + } +#endif + __inet6_hash(&tcp_hashinfo, newsk); inet_inherit_port(&tcp_hashinfo, sk, newsk); @@ -1067,6 +1569,11 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (skb->protocol == htons(ETH_P_IP)) return tcp_v4_do_rcv(sk, skb); +#ifdef CONFIG_TCP_MD5SIG + if (tcp_v6_inbound_md5_hash (sk, skb)) + goto discard; +#endif + if (sk_filter(sk, skb)) goto discard; @@ -1132,7 +1639,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) return 0; reset: - tcp_v6_send_reset(skb); + tcp_v6_send_reset(sk, skb); discard: if (opt_skb) __kfree_skb(opt_skb); @@ -1257,7 +1764,7 @@ no_tcp_socket: bad_packet: TCP_INC_STATS_BH(TCP_MIB_INERRS); } else { - tcp_v6_send_reset(skb); + tcp_v6_send_reset(NULL, skb); } discard_it: @@ -1336,6 +1843,15 @@ static struct inet_connection_sock_af_ops ipv6_specific = { #endif }; +static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v6_md5_lookup, + .calc_md5_hash = tcp_v6_calc_md5_hash, + .md5_add = tcp_v6_md5_add_func, + .md5_parse = tcp_v6_parse_md5_keys, +#endif +}; + /* * TCP over IPv4 via INET6 API */ @@ -1358,6 +1874,15 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { #endif }; +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { +#ifdef CONFIG_TCP_MD5SIG + .md5_lookup = tcp_v4_md5_lookup, + .calc_md5_hash = tcp_v4_calc_md5_hash, + .md5_add = tcp_v6_md5_add_func, + .md5_parse = tcp_v6_parse_md5_keys, +#endif +}; + /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. */ @@ -1397,6 +1922,10 @@ static int tcp_v6_init_sock(struct sock *sk) sk->sk_write_space = sk_stream_write_space; sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); +#ifdef CONFIG_TCP_MD5SIG + tp->af_specific = &tcp_sock_ipv6_specific; +#endif + sk->sk_sndbuf = sysctl_tcp_wmem[1]; sk->sk_rcvbuf = sysctl_tcp_rmem[1]; @@ -1407,6 +1936,11 @@ static int tcp_v6_init_sock(struct sock *sk) static int tcp_v6_destroy_sock(struct sock *sk) { +#ifdef CONFIG_TCP_MD5SIG + /* Clean up the MD5 key list */ + if (tcp_sk(sk)->md5sig_info) + tcp_v6_clear_md5_list(sk); +#endif tcp_v4_destroy_sock(sk); return inet6_destroy_sock(sk); } -- cgit v1.2.3-70-g09d2 From a928630a2ffeaf6aa9a6b78456935b6ab1be3066 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 14 Nov 2006 19:53:22 -0800 Subject: [TCP]: Fix some warning when MD5 is disabled. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just some mis-placed ifdefs: net/ipv4/tcp_minisocks.c: In function ‘tcp_twsk_destructor’: net/ipv4/tcp_minisocks.c:364: warning: unused variable ‘twsk’ net/ipv6/tcp_ipv6.c:1846: warning: ‘tcp_sock_ipv6_specific’ defined but not used net/ipv6/tcp_ipv6.c:1877: warning: ‘tcp_sock_ipv6_mapped_specific’ defined but not used Signed-off-by: David S. Miller --- net/ipv4/tcp_minisocks.c | 2 +- net/ipv6/tcp_ipv6.c | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index ac55d8892cf..4a0ee901a88 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -361,8 +361,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) void tcp_twsk_destructor(struct sock *sk) { - struct tcp_timewait_sock *twsk = tcp_twsk(sk); #ifdef CONFIG_TCP_MD5SIG + struct tcp_timewait_sock *twsk = tcp_twsk(sk); if (twsk->tw_md5_keylen) tcp_put_md5sig_pool(); #endif diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 663d1d23801..edef7eef834 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -81,8 +81,10 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); static struct inet_connection_sock_af_ops ipv6_mapped; static struct inet_connection_sock_af_ops ipv6_specific; +#ifdef CONFIG_TCP_MD5SIG static struct tcp_sock_af_ops tcp_sock_ipv6_specific; static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; +#endif static int tcp_v6_get_port(struct sock *sk, unsigned short snum) { @@ -1843,14 +1845,14 @@ static struct inet_connection_sock_af_ops ipv6_specific = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { .md5_lookup = tcp_v6_md5_lookup, .calc_md5_hash = tcp_v6_calc_md5_hash, .md5_add = tcp_v6_md5_add_func, .md5_parse = tcp_v6_parse_md5_keys, -#endif }; +#endif /* * TCP over IPv4 via INET6 API @@ -1874,14 +1876,14 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, .md5_add = tcp_v6_md5_add_func, .md5_parse = tcp_v6_parse_md5_keys, -#endif }; +#endif /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. -- cgit v1.2.3-70-g09d2 From e69a4adc669fe210817ec50ae3f9a7a5ad62d4e8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:56:00 -0800 Subject: [IPV6]: Misc endianness annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/addrconf.h | 8 ++++---- include/net/ip6_route.h | 2 +- include/net/ipv6.h | 2 +- include/net/ndisc.h | 4 ++-- net/ipv6/addrconf.c | 2 +- net/ipv6/af_inet6.c | 4 ++-- net/ipv6/datagram.c | 6 +++--- net/ipv6/exthdrs.c | 2 +- net/ipv6/exthdrs_core.c | 2 +- net/ipv6/inet6_connection_sock.c | 8 ++++---- net/ipv6/ip6_fib.c | 8 ++++---- net/ipv6/ip6_tunnel.c | 2 +- net/ipv6/mip6.c | 4 ++-- net/ipv6/ndisc.c | 5 +++-- net/ipv6/netfilter/ip6_tables.c | 3 ++- net/ipv6/netfilter/ip6t_LOG.c | 4 ++-- net/ipv6/raw.c | 2 +- net/ipv6/reassembly.c | 26 +++++++++++++------------- net/ipv6/route.c | 2 +- net/ipv6/sit.c | 18 +++++++++--------- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/udp.c | 4 ++-- 22 files changed, 62 insertions(+), 60 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 44f1b673f91..88df8fc814e 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -35,9 +35,9 @@ struct prefix_info { #else #error "Please fix " #endif - __u32 valid; - __u32 prefered; - __u32 reserved2; + __be32 valid; + __be32 prefered; + __be32 reserved2; struct in6_addr prefix; }; @@ -183,7 +183,7 @@ static __inline__ u8 ipv6_addr_hash(const struct in6_addr *addr) * This will include the IEEE address token on links that support it. */ - word = addr->s6_addr32[2] ^ addr->s6_addr32[3]; + word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); word ^= (word >> 16); word ^= (word >> 8); diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index c14b70ed4c5..4e927ebd1cb 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -20,7 +20,7 @@ struct route_info { route_pref:2, reserved_h:3; #endif - __u32 lifetime; + __be32 lifetime; __u8 prefix[0]; /* 0,8 or 16 */ }; diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 9390649bbfe..4ca9e93decc 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -563,7 +563,7 @@ extern int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len); extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); -extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port, +extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, __be16 port, u32 info, u8 *payload); extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info); diff --git a/include/net/ndisc.h b/include/net/ndisc.h index d3915dabe6d..475b10c575b 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -66,8 +66,8 @@ struct rs_msg { struct ra_msg { struct icmp6hdr icmph; - __u32 reachable_time; - __u32 retrans_timer; + __be32 reachable_time; + __be32 retrans_timer; }; struct nd_opt_hdr { diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 052f99eaf2a..b41c5d8b278 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -232,7 +232,7 @@ static inline unsigned ipv6_addr_scope2type(unsigned scope) int __ipv6_addr_type(const struct in6_addr *addr) { - u32 st; + __be32 st; st = addr->s6_addr32[0]; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 1eb1c7f261d..87c8f54872b 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -222,7 +222,7 @@ lookup_protocol: * the user to assign a number at socket * creation time automatically shares. */ - inet->sport = ntohs(inet->num); + inet->sport = htons(inet->num); sk->sk_prot->hash(sk); } if (sk->sk_prot->init) { @@ -342,7 +342,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; - inet->sport = ntohs(inet->num); + inet->sport = htons(inet->num); inet->dport = 0; inet->daddr = 0; out: diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index a67434af691..5c94fea90e9 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -207,7 +207,7 @@ out: } void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, - u16 port, u32 info, u8 *payload) + __be16 port, u32 info, u8 *payload) { struct ipv6_pinfo *np = inet6_sk(sk); struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw; @@ -324,7 +324,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) } else { ipv6_addr_set(&sin->sin6_addr, 0, 0, htonl(0xffff), - *(u32*)(skb->nh.raw + serr->addr_offset)); + *(__be32*)(skb->nh.raw + serr->addr_offset)); } } @@ -397,7 +397,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) } if (np->rxopt.bits.rxtclass) { - int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff; + int tclass = (ntohl(*(__be32 *)skb->nh.ipv6h) >> 20) & 0xff; put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 27829cc4ce8..0711f92d6a1 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -655,7 +655,7 @@ static int ipv6_hop_jumbo(struct sk_buff **skbp, int optoff) goto drop; } - pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2)); + pkt_len = ntohl(*(__be32*)(skb->nh.raw+optoff+2)); if (pkt_len <= IPV6_MAXPLEN) { IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2); diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 315bc1fbec3..21cbbbddaf4 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c @@ -77,7 +77,7 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp) if (hp == NULL) return -1; if (nexthdr == NEXTHDR_FRAGMENT) { - unsigned short _frag_off, *fp; + __be16 _frag_off, *fp; fp = skb_header_pointer(skb, start+offsetof(struct frag_hdr, frag_off), diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index c598962eaa4..c700302ad51 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c @@ -55,16 +55,16 @@ EXPORT_SYMBOL_GPL(inet6_csk_bind_conflict); static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport, const u32 rnd, const u16 synq_hsize) { - u32 a = raddr->s6_addr32[0]; - u32 b = raddr->s6_addr32[1]; - u32 c = raddr->s6_addr32[2]; + u32 a = (__force u32)raddr->s6_addr32[0]; + u32 b = (__force u32)raddr->s6_addr32[1]; + u32 c = (__force u32)raddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += rnd; __jhash_mix(a, b, c); - a += raddr->s6_addr32[3]; + a += (__force u32)raddr->s6_addr32[3]; b += (__force u32)rport; __jhash_mix(a, b, c); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index f98ca30d7c1..bf526115e51 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -139,9 +139,9 @@ static __inline__ u32 fib6_new_sernum(void) * test bit */ -static __inline__ int addr_bit_set(void *token, int fn_bit) +static __inline__ __be32 addr_bit_set(void *token, int fn_bit) { - __u32 *addr = token; + __be32 *addr = token; return htonl(1 << ((~fn_bit)&0x1F)) & addr[fn_bit>>5]; } @@ -434,7 +434,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, struct fib6_node *pn = NULL; struct rt6key *key; int bit; - int dir = 0; + __be32 dir = 0; __u32 sernum = fib6_new_sernum(); RT6_TRACE("fib6_add_1\n"); @@ -829,7 +829,7 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, struct lookup_args *args) { struct fib6_node *fn; - int dir; + __be32 dir; if (unlikely(args->offset == 0)) return NULL; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 80a11909159..25bc5ed4910 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -66,7 +66,7 @@ MODULE_LICENSE("GPL"); #define HASH_SIZE 32 -#define HASH(addr) (((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ +#define HASH(addr) ((__force u32)((addr)->s6_addr32[0] ^ (addr)->s6_addr32[1] ^ \ (addr)->s6_addr32[2] ^ (addr)->s6_addr32[3]) & \ (HASH_SIZE - 1)) diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 7ccdc8fc5a3..be7dd7db65d 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -262,10 +262,10 @@ static int mip6_destopt_reject(struct xfrm_state *x, struct sk_buff *skb, struct sel.proto = fl->proto; sel.dport = xfrm_flowi_dport(fl); if (sel.dport) - sel.dport_mask = ~((__u16)0); + sel.dport_mask = htons(~0); sel.sport = xfrm_flowi_sport(fl); if (sel.sport) - sel.sport_mask = ~((__u16)0); + sel.sport_mask = htons(~0); sel.ifindex = fl->oif; err = km_report(IPPROTO_DSTOPTS, &sel, diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 1342be8b4cd..56ea9283730 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1267,10 +1267,11 @@ skip_defrtr: } if (ndopts.nd_opts_mtu) { + __be32 n; u32 mtu; - memcpy(&mtu, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); - mtu = ntohl(mtu); + memcpy(&n, ((u8*)(ndopts.nd_opts_mtu+1))+2, sizeof(mtu)); + mtu = ntohl(n); if (mtu < IPV6_MIN_MTU || mtu > skb->dev->mtu) { ND_PRINTK2(KERN_WARNING diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 204e02162d4..f63fb86d7c7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1481,7 +1481,8 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, if (hp == NULL) return -EBADMSG; if (nexthdr == NEXTHDR_FRAGMENT) { - unsigned short _frag_off, *fp; + unsigned short _frag_off; + __be16 *fp; fp = skb_header_pointer(skb, start+offsetof(struct frag_hdr, frag_off), diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index 3cb6bb79cc0..f4857cf97f0 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c @@ -69,9 +69,9 @@ static void dump_packet(const struct nf_loginfo *info, /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ntohs(ih->payload_len) + sizeof(struct ipv6hdr), - (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20, + (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, ih->hop_limit, - (ntohl(*(u_int32_t *)ih) & 0x000fffff)); + (ntohl(*(__be32 *)ih) & 0x000fffff)); fragment = 0; ptr = ip6hoff + sizeof(struct ipv6hdr); diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 813fa1d9686..b03040a2081 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -220,7 +220,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; - __u32 v4addr = 0; + __be32 v4addr = 0; int addr_type; int err; diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 3af0d5a6cee..6f9a9046510 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -77,7 +77,7 @@ struct frag_queue struct hlist_node list; struct list_head lru_list; /* lru list member */ - __u32 id; /* fragment id */ + __be32 id; /* fragment id */ struct in6_addr saddr; struct in6_addr daddr; @@ -125,28 +125,28 @@ static __inline__ void fq_unlink(struct frag_queue *fq) * callers should be careful not to use the hash value outside the ipfrag_lock * as doing so could race with ipfrag_hash_rnd being recalculated. */ -static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr, +static unsigned int ip6qhashfn(__be32 id, struct in6_addr *saddr, struct in6_addr *daddr) { u32 a, b, c; - a = saddr->s6_addr32[0]; - b = saddr->s6_addr32[1]; - c = saddr->s6_addr32[2]; + a = (__force u32)saddr->s6_addr32[0]; + b = (__force u32)saddr->s6_addr32[1]; + c = (__force u32)saddr->s6_addr32[2]; a += JHASH_GOLDEN_RATIO; b += JHASH_GOLDEN_RATIO; c += ip6_frag_hash_rnd; __jhash_mix(a, b, c); - a += saddr->s6_addr32[3]; - b += daddr->s6_addr32[0]; - c += daddr->s6_addr32[1]; + a += (__force u32)saddr->s6_addr32[3]; + b += (__force u32)daddr->s6_addr32[0]; + c += (__force u32)daddr->s6_addr32[1]; __jhash_mix(a, b, c); - a += daddr->s6_addr32[2]; - b += daddr->s6_addr32[3]; - c += id; + a += (__force u32)daddr->s6_addr32[2]; + b += (__force u32)daddr->s6_addr32[3]; + c += (__force u32)id; __jhash_mix(a, b, c); return c & (IP6Q_HASHSZ - 1); @@ -370,7 +370,7 @@ static struct frag_queue *ip6_frag_intern(struct frag_queue *fq_in) static struct frag_queue * -ip6_frag_create(u32 id, struct in6_addr *src, struct in6_addr *dst, +ip6_frag_create(__be32 id, struct in6_addr *src, struct in6_addr *dst, struct inet6_dev *idev) { struct frag_queue *fq; @@ -396,7 +396,7 @@ oom: } static __inline__ struct frag_queue * -fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst, +fq_find(__be32 id, struct in6_addr *src, struct in6_addr *dst, struct inet6_dev *idev) { struct frag_queue *fq; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index a6472cb9054..0bf17a3cf08 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -440,7 +440,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, if (pref == ICMPV6_ROUTER_PREF_INVALID) pref = ICMPV6_ROUTER_PREF_MEDIUM; - lifetime = htonl(rinfo->lifetime); + lifetime = ntohl(rinfo->lifetime); if (lifetime == 0xffffffff) { /* infinity */ } else if (lifetime > 0x7fffffff/HZ) { diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index be699f85b2c..85ff3dc4514 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -60,7 +60,7 @@ */ #define HASH_SIZE 16 -#define HASH(addr) ((addr^(addr>>4))&0xF) +#define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF) static int ipip6_fb_tunnel_init(struct net_device *dev); static int ipip6_tunnel_init(struct net_device *dev); @@ -76,7 +76,7 @@ static struct ip_tunnel **tunnels[4] = { tunnels_wc, tunnels_l, tunnels_r, tunne static DEFINE_RWLOCK(ipip6_lock); -static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) +static struct ip_tunnel * ipip6_tunnel_lookup(__be32 remote, __be32 local) { unsigned h0 = HASH(remote); unsigned h1 = HASH(local); @@ -102,8 +102,8 @@ static struct ip_tunnel * ipip6_tunnel_lookup(u32 remote, u32 local) static struct ip_tunnel ** ipip6_bucket(struct ip_tunnel *t) { - u32 remote = t->parms.iph.daddr; - u32 local = t->parms.iph.saddr; + __be32 remote = t->parms.iph.daddr; + __be32 local = t->parms.iph.saddr; unsigned h = 0; int prio = 0; @@ -144,8 +144,8 @@ static void ipip6_tunnel_link(struct ip_tunnel *t) static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int create) { - u32 remote = parms->iph.daddr; - u32 local = parms->iph.saddr; + __be32 remote = parms->iph.daddr; + __be32 local = parms->iph.saddr; struct ip_tunnel *t, **tp, *nt; struct net_device *dev; unsigned h = 0; @@ -405,9 +405,9 @@ out: /* Returns the embedded IPv4 address if the IPv6 address comes from 6to4 (RFC 3056) addr space */ -static inline u32 try_6to4(struct in6_addr *v6dst) +static inline __be32 try_6to4(struct in6_addr *v6dst) { - u32 dst = 0; + __be32 dst = 0; if (v6dst->s6_addr16[0] == htons(0x2002)) { /* 6to4 v6 addr has 16 bits prefix, 32 v4addr, 16 SLA, ... */ @@ -432,7 +432,7 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ - u32 dst = tiph->daddr; + __be32 dst = tiph->daddr; int mtu; struct in6_addr *addr6; int addr_type; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index edef7eef834..53f270995d8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1084,7 +1084,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, struct sk_buff *buff; struct flowi fl; int tot_len = sizeof(struct tcphdr); - u32 *topt; + __be32 *topt; #ifdef CONFIG_TCP_MD5SIG struct tcp_md5sig_key *key; struct tcp_md5sig_key tw_key; @@ -1128,7 +1128,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, t1->ack = 1; t1->window = htons(win); - topt = (u32*)(t1 + 1); + topt = (__be32 *)(t1 + 1); if (ts) { *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 5a64027bf2f..e6e1f85f1bb 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -298,8 +298,8 @@ drop: } static struct sock *udp_v6_mcast_next(struct sock *sk, - u16 loc_port, struct in6_addr *loc_addr, - u16 rmt_port, struct in6_addr *rmt_addr, + __be16 loc_port, struct in6_addr *loc_addr, + __be16 rmt_port, struct in6_addr *rmt_addr, int dif) { struct hlist_node *node; -- cgit v1.2.3-70-g09d2 From 868c86bcb5bdea7ed8d45979b17bb919af9254db Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:35:48 -0800 Subject: [NET]: annotate csum_ipv6_magic() callers in net/* Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/udp.h | 4 ++-- include/net/udplite.h | 4 ++-- net/dccp/ipv6.c | 2 +- net/ipv6/icmp.c | 14 +++++++------- net/ipv6/mcast.c | 4 ++-- net/ipv6/netfilter.c | 5 +++-- net/ipv6/raw.c | 11 +++++------ net/ipv6/tcp_ipv6.c | 8 ++++---- net/ipv6/udp.c | 9 +++++---- 9 files changed, 31 insertions(+), 30 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/net/udp.h b/include/net/udp.h index 4f0626735ed..39e825a6909 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -89,9 +89,9 @@ static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb) * @skb: sk_buff containing the filled-in UDP header * (checksum field must be zeroed out) */ -static inline u32 udp_csum_outgoing(struct sock *sk, struct sk_buff *skb) +static inline __wsum udp_csum_outgoing(struct sock *sk, struct sk_buff *skb) { - u32 csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0); + __wsum csum = csum_partial(skb->h.raw, sizeof(struct udphdr), 0); skb_queue_walk(&sk->sk_write_queue, skb) { csum = csum_add(csum, skb->csum); diff --git a/include/net/udplite.h b/include/net/udplite.h index 1473b3e4904..406eb755b34 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -124,10 +124,10 @@ static inline int udplite_sender_cscov(struct udp_sock *up, struct udphdr *uh) return cscov; } -static inline u32 udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) +static inline __wsum udplite_csum_outgoing(struct sock *sk, struct sk_buff *skb) { - u32 csum = 0; int off, len, cscov = udplite_sender_cscov(udp_sk(sk), skb->h.uh); + __wsum csum = 0; skb->ip_summed = CHECKSUM_NONE; /* no HW support for checksumming */ diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index e0a0607862e..f28e406a4a1 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -59,7 +59,7 @@ static void dccp_v6_hash(struct sock *sk) } /* add pseudo-header to DCCP checksum stored in skb->csum */ -static inline u16 dccp_v6_csum_finish(struct sk_buff *skb, +static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, struct in6_addr *saddr, struct in6_addr *daddr) { diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index bd51847acd5..4ab8acf37b5 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -234,7 +234,7 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct len, fl->proto, skb->csum); } else { - u32 tmp_csum = 0; + __wsum tmp_csum = 0; skb_queue_walk(&sk->sk_write_queue, skb) { tmp_csum = csum_add(tmp_csum, skb->csum); @@ -242,10 +242,10 @@ static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct tmp_csum = csum_partial((char *)icmp6h, sizeof(struct icmp6hdr), tmp_csum); - tmp_csum = csum_ipv6_magic(&fl->fl6_src, - &fl->fl6_dst, - len, fl->proto, tmp_csum); - icmp6h->icmp6_cksum = tmp_csum; + icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src, + &fl->fl6_dst, + len, fl->proto, + tmp_csum); } ip6_push_pending_frames(sk); out: @@ -636,8 +636,8 @@ static int icmpv6_rcv(struct sk_buff **pskb) break; /* fall through */ case CHECKSUM_NONE: - skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, - IPPROTO_ICMPV6, 0); + skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, + IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", NIP6(*saddr), NIP6(*daddr)); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index c006d02be8b..a1c231a04ac 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -91,7 +91,7 @@ struct mld2_grec { struct mld2_report { __u8 type; __u8 resv1; - __u16 csum; + __sum16 csum; __be16 resv2; __be16 ngrec; struct mld2_grec grec[0]; @@ -100,7 +100,7 @@ struct mld2_report { struct mld2_query { __u8 type; __u8 code; - __u16 csum; + __sum16 csum; __be16 mrc; __be16 resv1; struct in6_addr mca; diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 646a47456fd..8d1b542806c 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -100,12 +100,13 @@ unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, } /* fall through */ case CHECKSUM_NONE: - skb->csum = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, + skb->csum = ~csum_unfold( + csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr, skb->len - dataoff, protocol, csum_sub(0, skb_checksum(skb, 0, - dataoff, 0))); + dataoff, 0)))); csum = __skb_checksum_complete(skb); } return csum; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index b03040a2081..cee5db27e8b 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -370,9 +370,9 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) skb->ip_summed = CHECKSUM_UNNECESSARY; } if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len, inet->num, 0); + skb->len, inet->num, 0)); if (inet->hdrincl) { if (skb_checksum_complete(skb)) { @@ -479,8 +479,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, int offset; int len; int total_len; - u32 tmp_csum; - u16 csum; + __wsum tmp_csum; + __sum16 csum; if (!rp->checksum) goto send; @@ -532,14 +532,13 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi *fl, if (unlikely(csum)) tmp_csum = csum_sub(tmp_csum, csum); - tmp_csum = csum_ipv6_magic(&fl->fl6_src, + csum = csum_ipv6_magic(&fl->fl6_src, &fl->fl6_dst, total_len, fl->proto, tmp_csum); if (tmp_csum == 0 && fl->proto == IPPROTO_UDP) tmp_csum = -1; - csum = tmp_csum; if (skb_store_bits(skb, offset, &csum, 2)) BUG(); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 53f270995d8..394bc54c5c2 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -105,10 +105,10 @@ static void tcp_v6_hash(struct sock *sk) } } -static __inline__ u16 tcp_v6_check(struct tcphdr *th, int len, +static __inline__ __sum16 tcp_v6_check(struct tcphdr *th, int len, struct in6_addr *saddr, struct in6_addr *daddr, - unsigned long base) + __wsum base) { return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); } @@ -1537,8 +1537,8 @@ static int tcp_v6_checksum_init(struct sk_buff *skb) } } - skb->csum = ~tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, 0); + skb->csum = ~csum_unfold(tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, 0)); if (skb->len <= 76) { return __skb_checksum_complete(skb); diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index e6e1f85f1bb..0d22008d522 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -383,9 +383,10 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh) skb->ip_summed = CHECKSUM_UNNECESSARY; if (skb->ip_summed != CHECKSUM_UNNECESSARY) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, - &skb->nh.ipv6h->daddr, - skb->len, IPPROTO_UDP, 0); + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, + &skb->nh.ipv6h->daddr, + ulen, IPPROTO_UDP, + 0)); return (UDP_SKB_CB(skb)->partial_cov = 0); } @@ -511,7 +512,7 @@ static int udp_v6_push_pending_frames(struct sock *sk, struct udp_sock *up) struct inet_sock *inet = inet_sk(sk); struct flowi *fl = &inet->cork.fl; int err = 0; - u32 csum = 0; + __wsum csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) -- cgit v1.2.3-70-g09d2 From b51655b958dfb1176bfcf99466231fdbef8751ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:40:42 -0800 Subject: [NET]: Annotate __skb_checksum_complete() and friends. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/linux/netfilter.h | 6 +++--- include/linux/netfilter_ipv4.h | 2 +- include/linux/netfilter_ipv6.h | 2 +- include/linux/skbuff.h | 2 +- include/net/tcp.h | 2 +- include/net/udp.h | 8 ++++---- net/core/datagram.c | 2 +- net/core/netpoll.c | 4 ++-- net/ipv4/netfilter.c | 4 ++-- net/ipv4/tcp_input.c | 4 ++-- net/ipv4/tcp_ipv4.c | 2 +- net/ipv6/netfilter.c | 4 ++-- net/ipv6/tcp_ipv6.c | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index b7e67d1d438..707bb2e53c4 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -290,7 +290,7 @@ extern u_int16_t nf_proto_csum_update(struct sk_buff *skb, struct nf_afinfo { unsigned short family; - unsigned int (*checksum)(struct sk_buff *skb, unsigned int hook, + __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); void (*saveroute)(const struct sk_buff *skb, struct nf_info *info); @@ -305,12 +305,12 @@ static inline struct nf_afinfo *nf_get_afinfo(unsigned short family) return rcu_dereference(nf_afinfo[family]); } -static inline unsigned int +static inline __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol, unsigned short family) { struct nf_afinfo *afinfo; - unsigned int csum = 0; + __sum16 csum = 0; rcu_read_lock(); afinfo = nf_get_afinfo(family); diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 5b63a231a76..5821eb5a0a3 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -79,7 +79,7 @@ enum nf_ip_hook_priorities { #ifdef __KERNEL__ extern int ip_route_me_harder(struct sk_buff **pskb, unsigned addr_type); extern int ip_xfrm_me_harder(struct sk_buff **pskb); -extern unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, +extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); #endif /*__KERNEL__*/ diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index d97e268cdfe..ab81a6dc94e 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -74,7 +74,7 @@ enum nf_ip6_hook_priorities { #ifdef CONFIG_NETFILTER extern int ip6_route_me_harder(struct sk_buff *skb); -extern unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, +extern __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); extern int ipv6_netfilter_init(void); diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 874ca029fbb..41753667541 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1398,7 +1398,7 @@ static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval * extern void __net_timestamp(struct sk_buff *skb); -extern unsigned int __skb_checksum_complete(struct sk_buff *skb); +extern __sum16 __skb_checksum_complete(struct sk_buff *skb); /** * skb_checksum_complete - Calculate checksum of an entire packet diff --git a/include/net/tcp.h b/include/net/tcp.h index 826aaecdb99..aa7989c5379 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -814,7 +814,7 @@ static inline __sum16 tcp_v4_check(struct tcphdr *th, int len, return csum_tcpudp_magic(saddr,daddr,len,IPPROTO_TCP,base); } -static inline int __tcp_checksum_complete(struct sk_buff *skb) +static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb) { return __skb_checksum_complete(skb); } diff --git a/include/net/udp.h b/include/net/udp.h index 39e825a6909..c5ccd9a3387 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -69,15 +69,15 @@ struct sk_buff; /* * Generic checksumming routines for UDP(-Lite) v4 and v6 */ -static inline u16 __udp_lib_checksum_complete(struct sk_buff *skb) +static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) { if (! UDP_SKB_CB(skb)->partial_cov) return __skb_checksum_complete(skb); - return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov, - skb->csum)); + return csum_fold(skb_checksum(skb, 0, UDP_SKB_CB(skb)->cscov, + skb->csum)); } -static __inline__ int udp_lib_checksum_complete(struct sk_buff *skb) +static inline __sum16 udp_lib_checksum_complete(struct sk_buff *skb) { return skb->ip_summed != CHECKSUM_UNNECESSARY && __udp_lib_checksum_complete(skb); diff --git a/net/core/datagram.c b/net/core/datagram.c index 0d9c9bac400..797fdd4352c 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -411,7 +411,7 @@ fault: return -EFAULT; } -unsigned int __skb_checksum_complete(struct sk_buff *skb) +__sum16 __skb_checksum_complete(struct sk_buff *skb) { __sum16 sum; diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 26ee1791aa0..8be3681d3d8 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -77,8 +77,8 @@ static void queue_process(void *p) } } -static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, - unsigned short ulen, __be32 saddr, __be32 daddr) +static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, + unsigned short ulen, __be32 saddr, __be32 daddr) { __wsum psum; diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index b797a37c01c..a68966059b5 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -162,11 +162,11 @@ static int nf_ip_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -unsigned int nf_ip_checksum(struct sk_buff *skb, unsigned int hook, +__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { struct iphdr *iph = skb->nh.iph; - unsigned int csum = 0; + __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6ab3423674b..9304034c0c4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3790,9 +3790,9 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) return err; } -static int __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) +static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) { - int result; + __sum16 result; if (sock_owned_by_user(sk)) { local_bh_enable(); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0ca8dead03b..dadf8027241 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1544,7 +1544,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) return sk; } -static int tcp_v4_checksum_init(struct sk_buff *skb) +static __sum16 tcp_v4_checksum_init(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_COMPLETE) { if (!tcp_v4_check(skb->h.th, skb->len, skb->nh.iph->saddr, diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 8d1b542806c..f6294e5bcb3 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -80,11 +80,11 @@ static int nf_ip6_reroute(struct sk_buff **pskb, const struct nf_info *info) return 0; } -unsigned int nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, +__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol) { struct ipv6hdr *ip6h = skb->nh.ipv6h; - unsigned int csum = 0; + __sum16 csum = 0; switch (skb->ip_summed) { case CHECKSUM_COMPLETE: diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 394bc54c5c2..147ce499f50 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1527,7 +1527,7 @@ out: return NULL; } -static int tcp_v6_checksum_init(struct sk_buff *skb) +static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) { if (skb->ip_summed == CHECKSUM_COMPLETE) { if (!tcp_v6_check(skb->h.th,skb->len,&skb->nh.ipv6h->saddr, -- cgit v1.2.3-70-g09d2 From af879cc704372ef762584e916129d19ffb39e844 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 17 Nov 2006 12:14:37 -0200 Subject: [IPV6]: Use kmemdup Code diff stats: [acme@newtoy net-2.6.20]$ codiff /tmp/ipv6.ko.before /tmp/ipv6.ko.after /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/ip6_output.c: ip6_output | -52 ip6_append_data | +2 2 functions changed, 2 bytes added, 52 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/addrconf.c: addrconf_sysctl_register | -27 1 function changed, 27 bytes removed /pub/scm/linux/kernel/git/acme/net-2.6.20/net/ipv6/tcp_ipv6.c: tcp_v6_syn_recv_sock | -32 tcp_v6_parse_md5_keys | -24 2 functions changed, 56 bytes removed /tmp/ipv6.ko.after: 5 functions changed, 2 bytes added, 135 bytes removed [acme@newtoy net-2.6.20]$ Signed-off-by: Arnaldo Carvalho de Melo --- net/ipv6/addrconf.c | 3 +-- net/ipv6/ah6.c | 3 +-- net/ipv6/ip6_output.c | 3 +-- net/ipv6/tcp_ipv6.c | 9 +++------ 4 files changed, 6 insertions(+), 12 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index b41c5d8b278..a5e8d207a51 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3969,10 +3969,9 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf struct addrconf_sysctl_table *t; char *dev_name = NULL; - t = kmalloc(sizeof(*t), GFP_KERNEL); + t = kmemdup(&addrconf_sysctl, sizeof(*t), GFP_KERNEL); if (t == NULL) return; - memcpy(t, &addrconf_sysctl, sizeof(*t)); for (i=0; t->addrconf_vars[i].data; i++) { t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; t->addrconf_vars[i].de = NULL; diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2d9e495cf69..12c5a4dec09 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -354,10 +354,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) if (!pskb_may_pull(skb, ah_hlen)) goto out; - tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hdr_len, GFP_ATOMIC); if (!tmp_hdr) goto out; - memcpy(tmp_hdr, skb->nh.raw, hdr_len); if (ipv6_clear_mutable_options(skb->nh.ipv6h, hdr_len, XFRM_POLICY_IN)) goto free_out; skb->nh.ipv6h->priority = 0; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 85f88927049..e05ecbb1412 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -624,14 +624,13 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) skb_shinfo(skb)->frag_list = NULL; /* BUILD HEADER */ - tmp_hdr = kmalloc(hlen, GFP_ATOMIC); + tmp_hdr = kmemdup(skb->nh.raw, hlen, GFP_ATOMIC); if (!tmp_hdr) { IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); return -ENOMEM; } *prevhdr = NEXTHDR_FRAGMENT; - memcpy(tmp_hdr, skb->nh.raw, hlen); __skb_pull(skb, hlen); fh = (struct frag_hdr*)__skb_push(skb, sizeof(struct frag_hdr)); skb->nh.raw = __skb_push(skb, hlen); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 147ce499f50..d2170da77e5 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -720,10 +720,9 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, tp->md5sig_info = p; } - newkey = kmalloc(cmd.tcpm_keylen, GFP_KERNEL); + newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, GFP_KERNEL); if (!newkey) return -ENOMEM; - memcpy(newkey, cmd.tcpm_key, cmd.tcpm_keylen); if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) { return tcp_v4_md5_do_add(sk, sin6->sin6_addr.s6_addr32[3], newkey, cmd.tcpm_keylen); @@ -1503,12 +1502,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, * memory, then we end up not copying the key * across. Shucks. */ - char *newkey = kmalloc(key->keylen, GFP_ATOMIC); - if (newkey) { - memcpy(newkey, key->key, key->keylen); + char *newkey = kmemdup(key->key, key->keylen, GFP_ATOMIC); + if (newkey != NULL) tcp_v6_md5_do_add(newsk, &inet6_sk(sk)->daddr, newkey, key->keylen); - } } #endif -- cgit v1.2.3-70-g09d2 From 8e5200f54062b8af0ed1d186ea0f113854786d89 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:06:37 -0800 Subject: [NET]: Fix assorted misannotations (from md5 and udplite merges). Signed-off-by: Al Viro Signed-off-by: David S. Miller --- include/net/tcp.h | 2 +- include/net/udp.h | 2 +- include/net/udplite.h | 4 ++-- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 4 ++-- net/ipv6/tcp_ipv6.c | 4 ++-- net/ipv6/udp.c | 2 +- net/ipv6/udplite.c | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/include/net/tcp.h b/include/net/tcp.h index aa7989c5379..c99774f15eb 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1154,7 +1154,7 @@ extern int tcp_v4_md5_do_add(struct sock *sk, u8 newkeylen); extern int tcp_v4_md5_do_del(struct sock *sk, - u32 addr); + __be32 addr); extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void); extern void tcp_free_md5sig_pool(void); diff --git a/include/net/udp.h b/include/net/udp.h index c5ccd9a3387..eac69ff0582 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -77,7 +77,7 @@ static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) skb->csum)); } -static inline __sum16 udp_lib_checksum_complete(struct sk_buff *skb) +static inline int udp_lib_checksum_complete(struct sk_buff *skb) { return skb->ip_summed != CHECKSUM_UNNECESSARY && __udp_lib_checksum_complete(skb); diff --git a/include/net/udplite.h b/include/net/udplite.h index 3abaab7b78c..67ac5142430 100644 --- a/include/net/udplite.h +++ b/include/net/udplite.h @@ -90,9 +90,9 @@ static __inline__ int udplite6_csum_init(struct sk_buff *skb, struct udphdr *uh) int rc = udplite_checksum_init(skb, uh); if (!rc) - skb->csum = ~csum_ipv6_magic(&skb->nh.ipv6h->saddr, + skb->csum = ~csum_unfold(csum_ipv6_magic(&skb->nh.ipv6h->saddr, &skb->nh.ipv6h->daddr, - skb->len, IPPROTO_UDPLITE, 0); + skb->len, IPPROTO_UDPLITE, 0)); return rc; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index b7d5522092e..e9d467124c4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1020,7 +1020,7 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, #ifdef CONFIG_TCP_MD5SIG_DEBUG int i; #endif - __u16 old_checksum; + __sum16 old_checksum; struct tcp_md5sig_pool *hp; struct tcp4_pseudohdr *bp; struct hash_desc *desc; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7eb76fbf1b4..28e4cf662ce 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -114,7 +114,7 @@ DEFINE_RWLOCK(udp_hash_lock); static int udp_port_rover; -static inline int __udp_lib_lport_inuse(__be16 num, struct hlist_head udptable[]) +static inline int __udp_lib_lport_inuse(__u16 num, struct hlist_head udptable[]) { struct sock *sk; struct hlist_node *node; @@ -455,7 +455,7 @@ static int udp_push_pending_frames(struct sock *sk, struct udp_sock *up) struct sk_buff *skb; struct udphdr *uh; int err = 0; - u32 csum = 0; + __wsum csum = 0; /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d2170da77e5..0adb337c4b7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -739,7 +739,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, struct scatterlist sg[4]; __u16 data_len; int block = 0; - __u16 cksum; + __sum16 cksum; struct tcp_md5sig_pool *hp; struct tcp6_pseudohdr *bp; struct hash_desc *desc; @@ -1032,7 +1032,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) #ifdef CONFIG_TCP_MD5SIG if (key) { - u32 *opt = (u32*)(t1 + 1); + __be32 *opt = (__be32*)(t1 + 1); opt[0] = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | (TCPOPT_MD5SIG << 8) | diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index efa8950ddd3..b3ea8af50a9 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -248,7 +248,7 @@ out: static __inline__ void udpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, int type, - int code, int offset, __u32 info ) + int code, int offset, __be32 info ) { return __udp6_lib_err(skb, opt, type, code, offset, info, udp_hash); } diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index e0ec5e63004..d4cafacc235 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -24,7 +24,7 @@ static __inline__ int udplitev6_rcv(struct sk_buff **pskb) static __inline__ void udplitev6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, - int type, int code, int offset, __u32 info) + int type, int code, int offset, __be32 info) { return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); } -- cgit v1.2.3-70-g09d2 From ff1dcadb1b55dbf471c5ed109dbbdf06bd19ef3b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:07:29 -0800 Subject: [NET]: Split skb->csum ... into anonymous union of __wsum and __u32 (csum and csum_offset resp.) Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/cassini.c | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/sk98lin/skge.c | 4 ++-- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.c | 2 +- include/linux/skbuff.h | 5 ++++- net/core/dev.c | 4 ++-- net/core/skbuff.c | 2 +- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/udp.c | 2 +- net/ipv6/tcp_ipv6.c | 4 ++-- 15 files changed, 22 insertions(+), 19 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 521c5b71023..fd2cc13f7d9 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2825,7 +2825,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = TX_DESC_CSUM_EN | CAS_BASE(TX_DESC_CSUM_START, csum_start_off) | diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7a0828869ec..32dde0adb68 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2826,7 +2826,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, context_desc = E1000_CONTEXT_DESC(*tx_ring, i); context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e09f575a3a3..7b127212e62 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1249,7 +1249,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) { struct ixgb_buffer *buffer_info; css = skb->h.raw - skb->data; - cso = (skb->h.raw + skb->csum) - skb->data; + cso = css + skb->csum_offset; i = adapter->tx_ring.next_to_use; context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 806081b5973..36350e6db1c 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1955,7 +1955,7 @@ again: flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { cksum_offset = (skb->h.raw - skb->data); - pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; + pseudo_hdr_offset = cksum_offset + skb->csum_offset; /* If the headers are excessively large, then we must * fall back to a software checksum */ if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index a5d41ebc9fb..12cbfd190dd 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1562,7 +1562,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && @@ -1681,7 +1681,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; Control = BMU_STFWD; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 27b537c8d5e..5513907e839 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2565,7 +2565,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) td->csum_offs = 0; td->csum_start = offset; - td->csum_write = offset + skb->csum; + td->csum_write = offset + skb->csum_offset; } else control = BMU_CHECK; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0ef1848b976..842abd9396c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1350,7 +1350,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) u32 tcpsum; tcpsum = offset << 16; /* sum start */ - tcpsum |= offset + skb->csum; /* sum write */ + tcpsum |= offset + skb->csum_offset; /* sum write */ ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; if (skb->nh.iph->protocol == IPPROTO_UDP) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 253e96e7ad2..334c6cfd659 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1030,7 +1030,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = (TXDCTRL_CENAB | (csum_start_off << 15) | diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9d7cd130c19..ec432ea879f 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2272,7 +2272,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 csum_start_off, csum_stuff_off; csum_start_off = (u32) (skb->h.raw - skb->data); - csum_stuff_off = (u32) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; tx_flags = (TXFLAG_OWN | TXFLAG_CSENABLE | ((csum_start_off << 14) & TXFLAG_CSBUFBEGIN) | diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index fcab543d79a..14ec16d2d9b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -274,7 +274,10 @@ struct sk_buff { unsigned int len, data_len, mac_len; - __wsum csum; + union { + __wsum csum; + __u32 csum_offset; + }; __u32 priority; __u8 local_df:1, cloned:1, diff --git a/net/core/dev.c b/net/core/dev.c index 1a36b17f4b5..59d058a3b50 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1191,9 +1191,9 @@ int skb_checksum_help(struct sk_buff *skb) offset = skb->tail - skb->h.raw; BUG_ON(offset <= 0); - BUG_ON(skb->csum + 2 > offset); + BUG_ON(skb->csum_offset + 2 > offset); - *(__sum16*)(skb->h.raw + skb->csum) = csum_fold(csum); + *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum); out_set_summed: skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 07c25d60192..a90bc439488 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1414,7 +1414,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) skb->len - csstart, 0); if (skb->ip_summed == CHECKSUM_PARTIAL) { - long csstuff = csstart + skb->csum; + long csstuff = csstart + skb->csum_offset; *((__sum16 *)(to + csstuff)) = csum_fold(csum); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e9d467124c4..4913f25e5ad 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -504,7 +504,7 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, csum_partial((char *)th, @@ -526,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 28e4cf662ce..1807a30694d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -422,7 +422,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, /* * Only one fragment on the socket. */ - skb->csum = offsetof(struct udphdr, check); + skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); } else { /* diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0adb337c4b7..517c50024bf 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -948,7 +948,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, csum_partial((char *)th, th->doff<<2, @@ -970,7 +970,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } -- cgit v1.2.3-70-g09d2 From f5b99bcdddfb2338227faad3489c24907f37ee8e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 30 Nov 2006 17:22:29 -0800 Subject: [NET]: Possible cleanups. This patch contains the following possible cleanups: - make the following needlessly global functions statis: - ipv4/tcp.c: __tcp_alloc_md5sig_pool() - ipv4/tcp_ipv4.c: tcp_v4_reqsk_md5_lookup() - ipv4/udplite.c: udplite_rcv() - ipv4/udplite.c: udplite_err() - make the following needlessly global structs static: - ipv4/tcp_ipv4.c: tcp_request_sock_ipv4_ops - ipv4/tcp_ipv4.c: tcp_sock_ipv4_specific - ipv6/tcp_ipv6.c: tcp_request_sock_ipv6_ops - net/ipv{4,6}/udplite.c: remove inline's from static functions (gcc should know best when to inline them) Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_ipv4.c | 8 ++++---- net/ipv4/udplite.c | 10 +++++----- net/ipv6/tcp_ipv6.c | 2 +- net/ipv6/udplite.c | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a6b228914b8..090c690627e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -2278,7 +2278,7 @@ void tcp_free_md5sig_pool(void) EXPORT_SYMBOL(tcp_free_md5sig_pool); -struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) +static struct tcp_md5sig_pool **__tcp_alloc_md5sig_pool(void) { int cpu; struct tcp_md5sig_pool **pool; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index dd3509a59fe..7684297d80a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -840,8 +840,8 @@ struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, EXPORT_SYMBOL(tcp_v4_md5_lookup); -struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, - struct request_sock *req) +static struct tcp_md5sig_key *tcp_v4_reqsk_md5_lookup(struct sock *sk, + struct request_sock *req) { return tcp_v4_md5_do_lookup(sk, inet_rsk(req)->rmt_addr); } @@ -1233,7 +1233,7 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; -struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { +static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v4_reqsk_md5_lookup, #endif @@ -1820,7 +1820,7 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; -struct tcp_sock_af_ops tcp_sock_ipv4_specific = { +static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 561de6d8c73..b28fe1edf98 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c @@ -18,23 +18,23 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics) __read_mostly; struct hlist_head udplite_hash[UDP_HTABLE_SIZE]; static int udplite_port_rover; -__inline__ int udplite_get_port(struct sock *sk, unsigned short p, - int (*c)(const struct sock *, const struct sock *)) +int udplite_get_port(struct sock *sk, unsigned short p, + int (*c)(const struct sock *, const struct sock *)) { return __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c); } -static __inline__ int udplite_v4_get_port(struct sock *sk, unsigned short snum) +static int udplite_v4_get_port(struct sock *sk, unsigned short snum) { return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal); } -__inline__ int udplite_rcv(struct sk_buff *skb) +static int udplite_rcv(struct sk_buff *skb) { return __udp4_lib_rcv(skb, udplite_hash, 1); } -__inline__ void udplite_err(struct sk_buff *skb, u32 info) +static void udplite_err(struct sk_buff *skb, u32 info) { return __udp4_lib_err(skb, info, udplite_hash); } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 517c50024bf..dd1a23b5a0f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -929,7 +929,7 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; -struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { +static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { #ifdef CONFIG_TCP_MD5SIG .md5_lookup = tcp_v6_reqsk_md5_lookup, #endif diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index d4cafacc235..629f97162fb 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -17,14 +17,14 @@ DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6) __read_mostly; -static __inline__ int udplitev6_rcv(struct sk_buff **pskb) +static int udplitev6_rcv(struct sk_buff **pskb) { return __udp6_lib_rcv(pskb, udplite_hash, 1); } -static __inline__ void udplitev6_err(struct sk_buff *skb, - struct inet6_skb_parm *opt, - int type, int code, int offset, __be32 info) +static void udplitev6_err(struct sk_buff *skb, + struct inet6_skb_parm *opt, + int type, int code, int offset, __be32 info) { return __udp6_lib_err(skb, opt, type, code, offset, info, udplite_hash); } @@ -35,7 +35,7 @@ static struct inet6_protocol udplitev6_protocol = { .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; -static __inline__ int udplite_v6_get_port(struct sock *sk, unsigned short snum) +static int udplite_v6_get_port(struct sock *sk, unsigned short snum) { return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal); } -- cgit v1.2.3-70-g09d2 From b6332e6cf9c9198c0f3b0fe37c2c57514dafe1b8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 30 Nov 2006 19:16:28 -0800 Subject: [TCP]: Fix warnings with TCP_MD5SIG disabled. Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- net/ipv4/tcp_ipv4.c | 8 ++++---- net/ipv6/tcp_ipv6.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'net/ipv6/tcp_ipv6.c') diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 7684297d80a..a1222d6968c 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1233,11 +1233,11 @@ struct request_sock_ops tcp_request_sock_ops __read_mostly = { .send_reset = tcp_v4_send_reset, }; -static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { .md5_lookup = tcp_v4_reqsk_md5_lookup, -#endif }; +#endif static struct timewait_sock_ops tcp_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp_timewait_sock), @@ -1820,14 +1820,14 @@ struct inet_connection_sock_af_ops ipv4_specific = { #endif }; -static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { .md5_lookup = tcp_v4_md5_lookup, .calc_md5_hash = tcp_v4_calc_md5_hash, .md5_add = tcp_v4_md5_add_func, .md5_parse = tcp_v4_parse_md5_keys, -#endif }; +#endif /* NOTE: A lot of things set to zero explicitly by call to * sk_alloc() so need not be done here. diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index dd1a23b5a0f..c25e930c2c6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -929,11 +929,11 @@ static struct request_sock_ops tcp6_request_sock_ops __read_mostly = { .send_reset = tcp_v6_send_reset }; -static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { #ifdef CONFIG_TCP_MD5SIG +static struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { .md5_lookup = tcp_v6_reqsk_md5_lookup, -#endif }; +#endif static struct timewait_sock_ops tcp6_timewait_sock_ops = { .twsk_obj_size = sizeof(struct tcp6_timewait_sock), -- cgit v1.2.3-70-g09d2