diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index b6f616cfd037..c8395e538dfb 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1515,74 +1515,75 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip) ip = NULL; else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) return; - if (ip != NULL) { - icp = (struct icmp *)((caddr_t)ip - - offsetof(struct icmp, icmp_ip)); - th = (struct tcphdr *)((caddr_t)ip - + (ip->ip_hl << 2)); - INP_INFO_RLOCK(&V_tcbinfo); - inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport, - ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL); - if (inp != NULL) { - if (!(inp->inp_flags & INP_TIMEWAIT) && - !(inp->inp_flags & INP_DROPPED) && - !(inp->inp_socket == NULL)) { - icmp_tcp_seq = htonl(th->th_seq); - tp = intotcpcb(inp); - if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) && - SEQ_LT(icmp_tcp_seq, tp->snd_max)) { - if (cmd == PRC_MSGSIZE) { - /* - * MTU discovery: - * If we got a needfrag set the MTU - * in the route to the suggested new - * value (if given) and then notify. - */ - bzero(&inc, sizeof(inc)); - inc.inc_faddr = faddr; - inc.inc_fibnum = - inp->inp_inc.inc_fibnum; - mtu = ntohs(icp->icmp_nextmtu); - /* - * If no alternative MTU was - * proposed, try the next smaller - * one. - */ - if (!mtu) - mtu = ip_next_mtu( - ntohs(ip->ip_len), 1); - if (mtu < V_tcp_minmss - + sizeof(struct tcpiphdr)) - mtu = V_tcp_minmss - + sizeof(struct tcpiphdr); - /* - * Only cache the MTU if it - * is smaller than the interface - * or route MTU. tcp_mtudisc() - * will do right thing by itself. - */ - if (mtu <= tcp_maxmtu(&inc, NULL)) - tcp_hc_updatemtu(&inc, mtu); - tcp_mtudisc(inp, mtu); - } else - inp = (*notify)(inp, - inetctlerrmap[cmd]); - } - } - if (inp != NULL) - INP_WUNLOCK(inp); - } else { - bzero(&inc, sizeof(inc)); - inc.inc_fport = th->th_dport; - inc.inc_lport = th->th_sport; - inc.inc_faddr = faddr; - inc.inc_laddr = ip->ip_src; - syncache_unreach(&inc, th); - } - INP_INFO_RUNLOCK(&V_tcbinfo); - } else + if (ip == NULL) { in_pcbnotifyall(&V_tcbinfo, faddr, inetctlerrmap[cmd], notify); + return; + } + + icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip)); + th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + INP_INFO_RLOCK(&V_tcbinfo); + inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport, ip->ip_src, + th->th_sport, INPLOOKUP_WLOCKPCB, NULL); + if (inp != NULL) { + if (!(inp->inp_flags & INP_TIMEWAIT) && + !(inp->inp_flags & INP_DROPPED) && + !(inp->inp_socket == NULL)) { + icmp_tcp_seq = htonl(th->th_seq); + tp = intotcpcb(inp); + if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) && + SEQ_LT(icmp_tcp_seq, tp->snd_max)) { + if (cmd == PRC_MSGSIZE) { + /* + * MTU discovery: + * If we got a needfrag set the MTU + * in the route to the suggested new + * value (if given) and then notify. + */ + bzero(&inc, sizeof(inc)); + inc.inc_faddr = faddr; + inc.inc_fibnum = + inp->inp_inc.inc_fibnum; + + mtu = ntohs(icp->icmp_nextmtu); + /* + * If no alternative MTU was + * proposed, try the next smaller + * one. + */ + if (!mtu) + mtu = ip_next_mtu( + ntohs(ip->ip_len), 1); + if (mtu < V_tcp_minmss + + sizeof(struct tcpiphdr)) + mtu = V_tcp_minmss + + sizeof(struct tcpiphdr); + /* + * Only cache the MTU if it + * is smaller than the interface + * or route MTU. tcp_mtudisc() + * will do right thing by itself. + */ + if (mtu <= tcp_maxmtu(&inc, NULL)) + tcp_hc_updatemtu(&inc, mtu); + tcp_mtudisc(inp, mtu); + } else + inp = (*notify)(inp, + inetctlerrmap[cmd]); + } + } + if (inp != NULL) + INP_WUNLOCK(inp); + } else { + bzero(&inc, sizeof(inc)); + inc.inc_fport = th->th_dport; + inc.inc_lport = th->th_sport; + inc.inc_faddr = faddr; + inc.inc_laddr = ip->ip_src; + syncache_unreach(&inc, th); + } + INP_INFO_RUNLOCK(&V_tcbinfo); } #endif /* INET */