内核协议栈 netfilter中tproxy新版本对比

 由于:linux 新内核tcp/ip协议栈中添加了 TCP_NEW_SYN_RECV; 所以 在判断sk是否为transparent 时 需要考虑其状态;

static bool tproxy_sk_is_transparent(struct sock *sk)
{
    switch (sk->sk_state) {
    case TCP_TIME_WAIT:
        if (inet_twsk(sk)->tw_transparent)
            return true;
        break;
    case TCP_NEW_SYN_RECV:
        if (inet_rsk(inet_reqsk(sk))->no_srccheck)
            return true;
        break;
    default:
        if (inet_sk(sk)->transparent)
            return true;
    }

    sock_gen_put(sk);
    return false;
}
/**
 * tcp_make_synack - Prepare a SYN-ACK.
 * sk: listener socket
 * dst: dst entry attached to the SYNACK
 * req: request_sock pointer
 *
 * Allocate one skb and build a SYNACK packet.
 * @dst is consumed : Caller should not use it again.
 */
struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
                struct request_sock *req,
                struct tcp_fastopen_cookie *foc,
                bool attach_req)
{
    struct inet_request_sock *ireq = inet_rsk(req);
    const struct tcp_sock *tp = tcp_sk(sk);
    struct tcp_md5sig_key *md5 = NULL;
    struct tcp_out_options opts;
    struct sk_buff *skb;
    int tcp_header_size;
    struct tcphdr *th;
    u16 user_mss;
    int mss;

    skb = alloc_skb(MAX_TCP_HEADER, GFP_ATOMIC);
    -------------------------------
    if (attach_req) {
        skb_set_owner_w(skb, req_to_sk(req));
    } else {
        /* sk is a const pointer, because we want to express multiple
         * cpu might call us concurrently.
         * sk->sk_wmem_alloc in an atomic, we can promote to rw.
         */
        skb_set_owner_w(skb, (struct sock *)sk);
    }

-----------------------------------
}

处理syn包回复syn_ack时, 设置回复报文skb结构时, 其skb->sk 可能指向req_sock 可能指向listen sk;此时和以前内核版本不一样;

所以后续处理报文以及判断此skb的transparent属性时 需要判断其sk具体指向以及数值

对于 sk 的释放:

/* All sockets share common refcount, but have different destructors */
void sock_gen_put(struct sock *sk)
{
    if (!atomic_dec_and_test(&sk->sk_refcnt))
        return;

    if (sk->sk_state == TCP_TIME_WAIT)
        inet_twsk_free(inet_twsk(sk));
    else if (sk->sk_state == TCP_NEW_SYN_RECV)
        reqsk_free(inet_reqsk(sk));
    else
        sk_free(sk);
}
EXPORT_SYMBOL_GPL(sock_gen_put);

void sock_edemux(struct sk_buff *skb)
{
    sock_gen_put(skb->sk);
}

/* assign a socket to the skb -- consumes sk */
static void
nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
{
  skb_orphan(skb);
  skb->sk = sk;
  skb->destructor = sock_edemux;
}

 

也就是需要分各种状态释放skb->sk

http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
原文地址:https://www.cnblogs.com/codestack/p/14443667.html