]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/ipv4/tcp_input.c
ipv4: coding style: comparison for inequality with NULL
[karo-tx-linux.git] / net / ipv4 / tcp_input.c
index 26f24995bd3dbd61088cbd917660f320d4546d58..df7e7fa1273333a963eddf799eebd2b5bf71e9ad 100644 (file)
@@ -866,7 +866,7 @@ static void tcp_update_reordering(struct sock *sk, const int metric,
 /* This must be called before lost_out is incremented */
 static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
 {
-       if ((tp->retransmit_skb_hint == NULL) ||
+       if (!tp->retransmit_skb_hint ||
            before(TCP_SKB_CB(skb)->seq,
                   TCP_SKB_CB(tp->retransmit_skb_hint)->seq))
                tp->retransmit_skb_hint = skb;
@@ -1256,7 +1256,7 @@ static u8 tcp_sacktag_one(struct sock *sk,
                fack_count += pcount;
 
                /* Lost marker hint past SACKed? Tweak RFC3517 cnt */
-               if (!tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) &&
+               if (!tcp_is_fack(tp) && tp->lost_skb_hint &&
                    before(start_seq, TCP_SKB_CB(tp->lost_skb_hint)->seq))
                        tp->lost_cnt_hint += pcount;
 
@@ -1535,7 +1535,7 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
                if (!before(TCP_SKB_CB(skb)->seq, end_seq))
                        break;
 
-               if ((next_dup != NULL) &&
+               if (next_dup  &&
                    before(TCP_SKB_CB(skb)->seq, next_dup->end_seq)) {
                        in_sack = tcp_match_skb_to_sack(sk, skb,
                                                        next_dup->start_seq,
@@ -1551,7 +1551,7 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
                if (in_sack <= 0) {
                        tmp = tcp_shift_skb_data(sk, skb, state,
                                                 start_seq, end_seq, dup_sack);
-                       if (tmp != NULL) {
+                       if (tmp) {
                                if (tmp != skb) {
                                        skb = tmp;
                                        continue;
@@ -1614,7 +1614,7 @@ static struct sk_buff *tcp_maybe_skipping_dsack(struct sk_buff *skb,
                                                struct tcp_sacktag_state *state,
                                                u32 skip_to_seq)
 {
-       if (next_dup == NULL)
+       if (!next_dup)
                return skb;
 
        if (before(next_dup->start_seq, skip_to_seq)) {
@@ -1783,7 +1783,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
                        if (tcp_highest_sack_seq(tp) == cache->end_seq) {
                                /* ...but better entrypoint exists! */
                                skb = tcp_highest_sack(sk);
-                               if (skb == NULL)
+                               if (!skb)
                                        break;
                                state.fack_count = tp->fackets_out;
                                cache++;
@@ -1798,7 +1798,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
 
                if (!before(start_seq, tcp_highest_sack_seq(tp))) {
                        skb = tcp_highest_sack(sk);
-                       if (skb == NULL)
+                       if (!skb)
                                break;
                        state.fack_count = tp->fackets_out;
                }
@@ -3321,6 +3321,36 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
        return flag;
 }
 
+/* Return true if we're currently rate-limiting out-of-window ACKs and
+ * thus shouldn't send a dupack right now. We rate-limit dupacks in
+ * response to out-of-window SYNs or ACKs to mitigate ACK loops or DoS
+ * attacks that send repeated SYNs or ACKs for the same connection. To
+ * do this, we do not send a duplicate SYNACK or ACK if the remote
+ * endpoint is sending out-of-window SYNs or pure ACKs at a high rate.
+ */
+bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,
+                         int mib_idx, u32 *last_oow_ack_time)
+{
+       /* Data packets without SYNs are not likely part of an ACK loop. */
+       if ((TCP_SKB_CB(skb)->seq != TCP_SKB_CB(skb)->end_seq) &&
+           !tcp_hdr(skb)->syn)
+               goto not_rate_limited;
+
+       if (*last_oow_ack_time) {
+               s32 elapsed = (s32)(tcp_time_stamp - *last_oow_ack_time);
+
+               if (0 <= elapsed && elapsed < sysctl_tcp_invalid_ratelimit) {
+                       NET_INC_STATS_BH(net, mib_idx);
+                       return true;    /* rate-limited: don't send yet! */
+               }
+       }
+
+       *last_oow_ack_time = tcp_time_stamp;
+
+not_rate_limited:
+       return false;   /* not rate-limited: go ahead, send dupack now! */
+}
+
 /* RFC 5961 7 [ACK Throttling] */
 static void tcp_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
 {
@@ -3668,7 +3698,7 @@ void tcp_parse_options(const struct sk_buff *skb,
                                 */
                                if (opsize < TCPOLEN_EXP_FASTOPEN_BASE ||
                                    get_unaligned_be16(ptr) != TCPOPT_FASTOPEN_MAGIC ||
-                                   foc == NULL || !th->syn || (opsize & 1))
+                                   !foc || !th->syn || (opsize & 1))
                                        break;
                                foc->len = opsize - TCPOLEN_EXP_FASTOPEN_BASE;
                                if (foc->len >= TCP_FASTOPEN_COOKIE_MIN &&
@@ -4639,7 +4669,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk)
        struct sk_buff *head;
        u32 start, end;
 
-       if (skb == NULL)
+       if (!skb)
                return;
 
        start = TCP_SKB_CB(skb)->seq;
@@ -5094,7 +5124,7 @@ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 {
        struct tcp_sock *tp = tcp_sk(sk);
 
-       if (unlikely(sk->sk_rx_dst == NULL))
+       if (unlikely(!sk->sk_rx_dst))
                inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);
        /*
         *      Header prediction.
@@ -5291,7 +5321,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
 
        tcp_set_state(sk, TCP_ESTABLISHED);
 
-       if (skb != NULL) {
+       if (skb) {
                icsk->icsk_af_ops->sk_rx_dst_set(sk, skb);
                security_inet_conn_established(sk, skb);
        }
@@ -5660,11 +5690,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        }
 
        req = tp->fastopen_rsk;
-       if (req != NULL) {
+       if (req) {
                WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
-               if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
+               if (!tcp_check_req(sk, skb, req, true))
                        goto discard;
        }
 
@@ -5750,7 +5780,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                 * ACK we have received, this would have acknowledged
                 * our SYNACK so stop the SYNACK timer.
                 */
-               if (req != NULL) {
+               if (req) {
                        /* Return RST if ack_seq is invalid.
                         * Note that RFC793 only says to generate a
                         * DUPACK for it but for TCP Fast Open it seems
@@ -5912,6 +5942,80 @@ static void tcp_ecn_create_request(struct request_sock *req,
                inet_rsk(req)->ecn_ok = 1;
 }
 
+static void tcp_openreq_init(struct request_sock *req,
+                            const struct tcp_options_received *rx_opt,
+                            struct sk_buff *skb, const struct sock *sk)
+{
+       struct inet_request_sock *ireq = inet_rsk(req);
+
+       req->rcv_wnd = 0;               /* So that tcp_send_synack() knows! */
+       req->cookie_ts = 0;
+       tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
+       tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
+       tcp_rsk(req)->snt_synack = tcp_time_stamp;
+       tcp_rsk(req)->last_oow_ack_time = 0;
+       req->mss = rx_opt->mss_clamp;
+       req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
+       ireq->tstamp_ok = rx_opt->tstamp_ok;
+       ireq->sack_ok = rx_opt->sack_ok;
+       ireq->snd_wscale = rx_opt->snd_wscale;
+       ireq->wscale_ok = rx_opt->wscale_ok;
+       ireq->acked = 0;
+       ireq->ecn_ok = 0;
+       ireq->ir_rmt_port = tcp_hdr(skb)->source;
+       ireq->ir_num = ntohs(tcp_hdr(skb)->dest);
+       ireq->ir_mark = inet_request_mark(sk, skb);
+}
+
+struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
+                                     struct sock *sk_listener)
+{
+       struct request_sock *req = reqsk_alloc(ops, sk_listener);
+
+       if (req) {
+               struct inet_request_sock *ireq = inet_rsk(req);
+
+               kmemcheck_annotate_bitfield(ireq, flags);
+               ireq->opt = NULL;
+               atomic64_set(&ireq->ir_cookie, 0);
+               ireq->ireq_state = TCP_NEW_SYN_RECV;
+               write_pnet(&ireq->ireq_net, sock_net(sk_listener));
+               ireq->ireq_family = sk_listener->sk_family;
+       }
+
+       return req;
+}
+EXPORT_SYMBOL(inet_reqsk_alloc);
+
+/*
+ * Return true if a syncookie should be sent
+ */
+static bool tcp_syn_flood_action(struct sock *sk,
+                                const struct sk_buff *skb,
+                                const char *proto)
+{
+       const char *msg = "Dropping request";
+       bool want_cookie = false;
+       struct listen_sock *lopt;
+
+#ifdef CONFIG_SYN_COOKIES
+       if (sysctl_tcp_syncookies) {
+               msg = "Sending cookies";
+               want_cookie = true;
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDOCOOKIES);
+       } else
+#endif
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPREQQFULLDROP);
+
+       lopt = inet_csk(sk)->icsk_accept_queue.listen_opt;
+       if (!lopt->synflood_warned && sysctl_tcp_syncookies != 2) {
+               lopt->synflood_warned = 1;
+               pr_info("%s: Possible SYN flooding on port %d. %s.  Check SNMP counters.\n",
+                       proto, ntohs(tcp_hdr(skb)->dest), msg);
+       }
+       return want_cookie;
+}
+
 int tcp_conn_request(struct request_sock_ops *rsk_ops,
                     const struct tcp_request_sock_ops *af_ops,
                     struct sock *sk, struct sk_buff *skb)
@@ -5949,7 +6053,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                goto drop;
        }
 
-       req = inet_reqsk_alloc(rsk_ops);
+       req = inet_reqsk_alloc(rsk_ops, sk);
        if (!req)
                goto drop;
 
@@ -5965,8 +6069,9 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 
        tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
        tcp_openreq_init(req, &tmp_opt, skb, sk);
-       write_pnet(&inet_rsk(req)->ireq_net, sock_net(sk));
-       atomic64_set(&inet_rsk(req)->ir_cookie, 0);
+
+       /* Note: tcp_v6_init_req() might override ir_iif for link locals */
+       inet_rsk(req)->ir_iif = sk->sk_bound_dev_if;
 
        af_ops->init_req(req, sk, skb);
 
@@ -6040,7 +6145,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                if (err || want_cookie)
                        goto drop_and_free;
 
-               tcp_rsk(req)->listener = NULL;
+               tcp_rsk(req)->tfo_listener = false;
                af_ops->queue_hash_add(sk, req, TCP_TIMEOUT_INIT);
        }