icmp port unreachable

端口不可达:

client------>server 结果server回复端口不可达,

由于是icmp报文; 到达client内核协议栈后进入icmp_rcv处理:

/*
 *    Deal with incoming ICMP packets.
 */
int icmp_rcv(struct sk_buff *skb)
{
    struct icmphdr *icmph;
    struct rtable *rt = skb_rtable(skb);
    struct net *net = dev_net(rt->dst.dev);
    bool success;

    
    success = icmp_pointers[icmph->type].handler(skb);

    if (success)  {
        consume_skb(skb);
        return 0;
    }
}
--->/*
 *    Handle ICMP_DEST_UNREACH, ICMP_TIME_EXCEED, ICMP_QUENCH, and
 *    ICMP_PARAMETERPROB.
 */

static bool icmp_unreach(struct sk_buff *skb)
{
    const struct iphdr *iph;
    struct icmphdr *icmph;
    struct net *net;
    u32 info = 0;

    net = dev_net(skb_dst(skb)->dev);

    /*
     *    Incomplete header ?
     *     Only checks for the IP header, there should be an
     *    additional check for longer headers in upper levels.
     */

    if (!pskb_may_pull(skb, sizeof(struct iphdr)))
        goto out_err;

    

    icmp_socket_deliver(skb, info);

out:
    return true;
out_err:
    __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
    return false;
}

static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
{
    const struct iphdr *iph = (const struct iphdr *) skb->data;
    const struct net_protocol *ipprot;
    int protocol = iph->protocol;

    /* Checkin full IP header plus 8 bytes of protocol to
     * avoid additional coding at protocol handlers.
     */
    if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) {
        __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS);
        return;
    }

    raw_icmp_error(skb, protocol, info);

    ipprot = rcu_dereference(inet_protos[protocol]);
    if (ipprot && ipprot->err_handler)
        ipprot->err_handler(skb, info);//----udp_err(struct sk_buff * skb, u32 info)
}

:最后根据 icmp里面的  控制信息找到对应协议处理;udp_err  tcp_v4_err等

然后唤醒进程 wake_up

原文地址:https://www.cnblogs.com/codestack/p/12863526.html