From nobody Tue Oct 4 03:57:35 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4MhP6l3RzGz4dl8f; Tue, 4 Oct 2022 03:57:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MhP6l3CwJz3sPn; Tue, 4 Oct 2022 03:57:35 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1664855855; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YWEzNQshjSN1TH5Dykir1+a3WnLa8Z8G3SZ6bU7z9A8=; b=jzBhEeEUZ9tGHU1GFd+E+8X1dAh+xzc5JvSAcllgiMUjwcFvP2xyOazKdpsqDfCnspvaz3 qt9BDOW+o5nmGdFhZlqlhc77ne21IKqjKCacejNab7iS6xBJxqJWTdclcuggr3LIqJLKmX Mm1ODc2KM0McfbQ0rkqtWE9ht3Mm3ANfHV9kAuzQnz45hnW7dkTOdGdbRW7XruqvoXkAMW 0qTIaHd2ub5JiX8Zx2UhGxE30AsrAjZvX7TY90rD/Dj2oE4fcA5K8Lu8OMLV6Tbs0aIckU H2Ialzbob6N0d2yS3cP/kaf8AtP8kt/+acVMUwmCcnff8YFwGJ22m5NBUns3Jg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4MhP6l2H8WzQxw; Tue, 4 Oct 2022 03:57:35 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2943vZLv015382; Tue, 4 Oct 2022 03:57:35 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2943vZ1W015381; Tue, 4 Oct 2022 03:57:35 GMT (envelope-from git) Date: Tue, 4 Oct 2022 03:57:35 GMT Message-Id: <202210040357.2943vZ1W015381@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: c0fc81e9138b - main - netinet*: remove dead code from TCP, UDP, SCTP control input List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c0fc81e9138b4bc636333285087f1c3e1c7bc1e5 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1664855855; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=YWEzNQshjSN1TH5Dykir1+a3WnLa8Z8G3SZ6bU7z9A8=; b=TOllqarDEfhGRKYyqc4dqpNtBWv3Pex9n3AaCTKhR6NkVgQV38mOC4utj7iydtYX81t0FJ rJyOjUVUmQ3fUbQPN80hgnrKBAmNTMBrIpzGqTJveCMpuyOHGAGXGdBn/FjQsvrwG8gjhz TvG/Hd/JryC4UKegxl/VgQxb9aK0R3acWVsAXGrg9k3WoNiip55lTAI4w08xgGNkrsRQsY CqmYdPfb/i2gflUQ4SaGhe6Wd5Km9EO43B1OIs4yhR5DiNWVdp2VwH9GOEYnkJFULc5QsQ nScf/pNFzgeBdOU0vETmINVVls3uLLOLUngov1OasqmsQBOzC1betp/mkYLzGw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1664855855; a=rsa-sha256; cv=none; b=tosQtF0R8EVcipIjHYmKZWGpBK8BQpF/081XXWue2spBWKsrbocKi8uS6puZikQ3NT++gG 6vrQEIzzCgb1Q0Q8rIrCuq5aRQI36ijpM2QlaD0pkRxm2KZjEeG86mVh/UkQL0BiR5wmWG MrXPQ+ZrWTeaek25xTq8hD4QmKDc5gWH8avXUe0OOEvjHQWuvw1gfVItT++x24DAxwIsNR lfGyRV66At6HXy6CbkU3LsqieEWjFbdysE54749e5Eb3YZLCy7gxIsS1J3gYIrLuKkm+Z9 hwt2D6aw+zpIseUNyv6aBxNzSV9fWybFhHGqWM+X8dymNyaKiil2G/ZQaIy6Ow== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=c0fc81e9138b4bc636333285087f1c3e1c7bc1e5 commit c0fc81e9138b4bc636333285087f1c3e1c7bc1e5 Author: Gleb Smirnoff AuthorDate: 2022-10-04 03:53:04 +0000 Commit: Gleb Smirnoff CommitDate: 2022-10-04 03:53:04 +0000 netinet*: remove dead code from TCP, UDP, SCTP control input Now these functions are called only from icmp*_input(). The pointer to the ICMP data is never NULL and cmd has a limited set of values. In the past the functions were demultiplexing control messages from ICMP layer, as well as internally generated events. In the latter case the the pointer to IP would be NULL. Differential revision: https://reviews.freebsd.org/D36729 --- sys/netinet/sctp_usrreq.c | 145 ++++++++++++++++---------------- sys/netinet/tcp_subr.c | 95 +++++++-------------- sys/netinet/udp_usrreq.c | 65 ++++++--------- sys/netinet6/sctp6_usrreq.c | 196 +++++++++++++++++++++----------------------- sys/netinet6/udp6_usrreq.c | 88 +++++++------------- 5 files changed, 242 insertions(+), 347 deletions(-) diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index fdb195d79656..4c70b618bf41 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -260,10 +260,9 @@ sctp_notify(struct sctp_inpcb *inp, } void -sctp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) +sctp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *inner_ip) { struct ip *outer_ip; - struct ip *inner_ip; struct sctphdr *sh; struct icmp *icmp; struct sctp_inpcb *inp; @@ -272,91 +271,85 @@ sctp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) struct sctp_init_chunk *ch; struct sockaddr_in src, dst; - if (PRC_IS_REDIRECT(cmd)) { - ip = NULL; - } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) { + if (inetctlerrmap[cmd] == 0) return; - } - if (ip != NULL) { - inner_ip = ip; - icmp = (struct icmp *)((caddr_t)inner_ip - - (sizeof(struct icmp) - sizeof(struct ip))); - outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); - sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2)); - memset(&src, 0, sizeof(struct sockaddr_in)); - src.sin_family = AF_INET; - src.sin_len = sizeof(struct sockaddr_in); - src.sin_port = sh->src_port; - src.sin_addr = inner_ip->ip_src; - memset(&dst, 0, sizeof(struct sockaddr_in)); - dst.sin_family = AF_INET; - dst.sin_len = sizeof(struct sockaddr_in); - dst.sin_port = sh->dest_port; - dst.sin_addr = inner_ip->ip_dst; - /* - * 'dst' holds the dest of the packet that failed to be - * sent. 'src' holds our local endpoint address. Thus we - * reverse the dst and the src in the lookup. - */ - inp = NULL; - net = NULL; - stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst, - (struct sockaddr *)&src, - &inp, &net, 1, - SCTP_DEFAULT_VRFID); - if ((stcb != NULL) && - (net != NULL) && - (inp != NULL)) { - /* Check the verification tag */ - if (ntohl(sh->v_tag) != 0) { + + icmp = (struct icmp *)((caddr_t)inner_ip - + (sizeof(struct icmp) - sizeof(struct ip))); + outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); + sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2)); + memset(&src, 0, sizeof(struct sockaddr_in)); + src.sin_family = AF_INET; + src.sin_len = sizeof(struct sockaddr_in); + src.sin_port = sh->src_port; + src.sin_addr = inner_ip->ip_src; + memset(&dst, 0, sizeof(struct sockaddr_in)); + dst.sin_family = AF_INET; + dst.sin_len = sizeof(struct sockaddr_in); + dst.sin_port = sh->dest_port; + dst.sin_addr = inner_ip->ip_dst; + /* + * 'dst' holds the dest of the packet that failed to be + * sent. 'src' holds our local endpoint address. Thus we + * reverse the dst and the src in the lookup. + */ + inp = NULL; + net = NULL; + stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst, + (struct sockaddr *)&src, + &inp, &net, 1, + SCTP_DEFAULT_VRFID); + if ((stcb != NULL) && + (net != NULL) && + (inp != NULL)) { + /* Check the verification tag */ + if (ntohl(sh->v_tag) != 0) { + /* + * This must be the verification tag used + * for sending out packets. We don't + * consider packets reflecting the + * verification tag. + */ + if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) { + SCTP_TCB_UNLOCK(stcb); + return; + } + } else { + if (ntohs(outer_ip->ip_len) >= + sizeof(struct ip) + + 8 + (inner_ip->ip_hl << 2) + 20) { /* - * This must be the verification tag used - * for sending out packets. We don't - * consider packets reflecting the - * verification tag. + * In this case we can check if we + * got an INIT chunk and if the + * initiate tag matches. */ - if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) { + ch = (struct sctp_init_chunk *)(sh + 1); + if ((ch->ch.chunk_type != SCTP_INITIATION) || + (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) { SCTP_TCB_UNLOCK(stcb); return; } } else { - if (ntohs(outer_ip->ip_len) >= - sizeof(struct ip) + - 8 + (inner_ip->ip_hl << 2) + 20) { - /* - * In this case we can check if we - * got an INIT chunk and if the - * initiate tag matches. - */ - ch = (struct sctp_init_chunk *)(sh + 1); - if ((ch->ch.chunk_type != SCTP_INITIATION) || - (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) { - SCTP_TCB_UNLOCK(stcb); - return; - } - } else { - SCTP_TCB_UNLOCK(stcb); - return; - } - } - sctp_notify(inp, stcb, net, - icmp->icmp_type, - icmp->icmp_code, - ntohs(inner_ip->ip_len), - (uint32_t)ntohs(icmp->icmp_nextmtu)); - } else { - if ((stcb == NULL) && (inp != NULL)) { - /* reduce ref-count */ - SCTP_INP_WLOCK(inp); - SCTP_INP_DECR_REF(inp); - SCTP_INP_WUNLOCK(inp); - } - if (stcb) { SCTP_TCB_UNLOCK(stcb); + return; } } + sctp_notify(inp, stcb, net, + icmp->icmp_type, + icmp->icmp_code, + ntohs(inner_ip->ip_len), + (uint32_t)ntohs(icmp->icmp_nextmtu)); + } else { + if ((stcb == NULL) && (inp != NULL)) { + /* reduce ref-count */ + SCTP_INP_WLOCK(inp); + SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); + } + if (stcb) { + SCTP_TCB_UNLOCK(stcb); + } } - return; } #endif diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index e88b3b92b193..7e9fe9e4ff5f 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -2866,39 +2866,27 @@ tcp_ctlinput_with_port(int cmd, struct sockaddr_in *sin, struct ip *ip, tcp_seq icmp_tcp_seq; int mtu; - if (cmd == PRC_MSGSIZE) + switch (cmd) { + case PRC_MSGSIZE: notify = tcp_mtudisc_notify; - else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || - cmd == PRC_UNREACH_PORT || cmd == PRC_UNREACH_PROTOCOL || - cmd == PRC_TIMXCEED_INTRANS) && ip) - notify = tcp_drop_syn_sent; - - /* - * Hostdead is ugly because it goes linearly through all PCBs. - * XXX: We never get this from ICMP, otherwise it makes an - * excellent DoS attack on machines with many connections. - */ - else if (cmd == PRC_HOSTDEAD) - ip = NULL; - else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) - return; + break; + case PRC_UNREACH_PORT: + case PRC_UNREACH_PROTOCOL: + case PRC_TIMXCEED_INTRANS: + case PRC_UNREACH_ADMIN_PROHIB: + if (V_icmp_may_rst) + notify = tcp_drop_syn_sent; + break; + } - if (ip == NULL) { - in_pcbnotifyall(&V_tcbinfo, sin->sin_addr, inetctlerrmap[cmd], - notify); + if (inetctlerrmap[cmd] == 0) return; - } icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip)); th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + icmp_tcp_seq = th->th_seq; inp = in_pcblookup(&V_tcbinfo, sin->sin_addr, th->th_dport, ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL); - if (inp != NULL && PRC_IS_REDIRECT(cmd)) { - /* signal EHOSTDOWN, as it flushes the cached route */ - inp = (*notify)(inp, EHOSTDOWN); - goto out; - } - icmp_tcp_seq = th->th_seq; if (inp != NULL) { if (!(inp->inp_flags & INP_TIMEWAIT) && !(inp->inp_flags & INP_DROPPED) && @@ -3029,7 +3017,6 @@ tcp6_ctlinput_with_port(int cmd, struct sockaddr_in6 *sin6, struct inpcb *inp; struct tcpcb *tp; struct icmp6_hdr *icmp6; - const struct sockaddr_in6 *sa6_src = NULL; struct in_conninfo inc; struct tcp_ports { uint16_t th_sport; @@ -3039,44 +3026,27 @@ tcp6_ctlinput_with_port(int cmd, struct sockaddr_in6 *sin6, unsigned int mtu; unsigned int off; - /* if the parameter is from icmp6, decode it. */ - if (ip6cp != NULL) { - icmp6 = ip6cp->ip6c_icmp6; - m = ip6cp->ip6c_m; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; - sa6_src = ip6cp->ip6c_src; - dst = ip6cp->ip6c_finaldst; - } else { - m = NULL; - ip6 = NULL; - off = 0; /* fool gcc */ - sa6_src = &sa6_any; - dst = NULL; - } + icmp6 = ip6cp->ip6c_icmp6; + m = ip6cp->ip6c_m; + ip6 = ip6cp->ip6c_ip6; + off = ip6cp->ip6c_off; + dst = ip6cp->ip6c_finaldst; - if (cmd == PRC_MSGSIZE) + switch (cmd) { + case PRC_MSGSIZE: notify = tcp_mtudisc_notify; - else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB || - cmd == PRC_UNREACH_PORT || cmd == PRC_UNREACH_PROTOCOL || - cmd == PRC_TIMXCEED_INTRANS) && ip6 != NULL) - notify = tcp_drop_syn_sent; - - /* - * Hostdead is ugly because it goes linearly through all PCBs. - * XXX: We never get this from ICMP, otherwise it makes an - * excellent DoS attack on machines with many connections. - */ - else if (cmd == PRC_HOSTDEAD) - ip6 = NULL; - else if ((unsigned)cmd >= PRC_NCMDS || inet6ctlerrmap[cmd] == 0) - return; + break; + case PRC_UNREACH_ADMIN_PROHIB: + case PRC_UNREACH_PORT: + case PRC_UNREACH_PROTOCOL: + case PRC_TIMXCEED_INTRANS: + if (V_icmp_may_rst) + notify = tcp_drop_syn_sent; + break; + } - if (ip6 == NULL) { - in6_pcbnotify(&V_tcbinfo, sin6, 0, sa6_src, 0, cmd, NULL, - notify); + if (inet6ctlerrmap[cmd] == 0) return; - } /* Check if we can safely get the ports from the tcp hdr */ if (m == NULL || @@ -3088,11 +3058,6 @@ tcp6_ctlinput_with_port(int cmd, struct sockaddr_in6 *sin6, m_copydata(m, off, sizeof(struct tcp_ports), (caddr_t)&t_ports); inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_dst, t_ports.th_dport, &ip6->ip6_src, t_ports.th_sport, INPLOOKUP_WLOCKPCB, NULL); - if (inp != NULL && PRC_IS_REDIRECT(cmd)) { - /* signal EHOSTDOWN, as it flushes the cached route */ - inp = (*notify)(inp, EHOSTDOWN); - goto out; - } off += sizeof(struct tcp_ports); if (m->m_pkthdr.len < (int32_t) (off + sizeof(tcp_seq))) { goto out; diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 372341a0351c..70474fa18f92 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -746,53 +746,34 @@ udp_common_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip, struct udphdr *uh; struct inpcb *inp; - if (PRC_IS_REDIRECT(cmd)) { - /* signal EHOSTDOWN, as it flushes the cached route */ - in_pcbnotifyall(pcbinfo, sin->sin_addr, EHOSTDOWN, udp_notify); + if (inetctlerrmap[cmd] == 0) return; - } - /* - * Hostdead is ugly because it goes linearly through all PCBs. - * - * XXX: We never get this from ICMP, otherwise it makes an excellent - * DoS attack on machines with many connections. - */ - if (cmd == PRC_HOSTDEAD) - ip = NULL; - else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) - return; - if (ip != NULL) { - uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); + inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, ip->ip_src, + uh->uh_sport, INPLOOKUP_WLOCKPCB, NULL); + if (inp != NULL) { + INP_WLOCK_ASSERT(inp); + if (inp->inp_socket != NULL) + udp_notify(inp, inetctlerrmap[cmd]); + INP_WUNLOCK(inp); + } else { inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, - ip->ip_src, uh->uh_sport, INPLOOKUP_WLOCKPCB, NULL); + ip->ip_src, uh->uh_sport, + INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { - INP_WLOCK_ASSERT(inp); - if (inp->inp_socket != NULL) { - udp_notify(inp, inetctlerrmap[cmd]); - } - INP_WUNLOCK(inp); - } else { - inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, - ip->ip_src, uh->uh_sport, - INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); - if (inp != NULL) { - struct udpcb *up; - void *ctx; - udp_tun_icmp_t *func; - - up = intoudpcb(inp); - ctx = up->u_tun_ctx; - func = up->u_icmp_func; - INP_RUNLOCK(inp); - if (func != NULL) - (*func)(cmd, (struct sockaddr *)sin, - ip, ctx); - } + struct udpcb *up; + void *ctx; + udp_tun_icmp_t *func; + + up = intoudpcb(inp); + ctx = up->u_tun_ctx; + func = up->u_icmp_func; + INP_RUNLOCK(inp); + if (func != NULL) + (*func)(cmd, (struct sockaddr *)sin, ip, ctx); } - } else - in_pcbnotifyall(pcbinfo, sin->sin_addr, inetctlerrmap[cmd], - udp_notify); + } } static void diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index 5a771b19bdb8..1d3a35b2bdef 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -256,124 +256,112 @@ sctp6_ctlinput(int cmd, struct sockaddr_in6 *pktdst, struct ip6ctlparam *ip6cp) struct sctphdr sh; struct sockaddr_in6 src, dst; - if ((unsigned)cmd >= PRC_NCMDS) { + if (inet6ctlerrmap[cmd] == 0) return; - } - if (PRC_IS_REDIRECT(cmd)) { - ip6cp = NULL; - } else if (inet6ctlerrmap[cmd] == 0) { + + if (ip6cp->ip6c_m == NULL) { return; } - if (ip6cp != NULL) { - /* - * XXX: We assume that when IPV6 is non NULL, M and OFF are - * valid. - */ - if (ip6cp->ip6c_m == NULL) { - return; - } - - /* - * Check if we can safely examine the ports and the - * verification tag of the SCTP common header. - */ - if (ip6cp->ip6c_m->m_pkthdr.len < - (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) { - return; - } + /* + * Check if we can safely examine the ports and the + * verification tag of the SCTP common header. + */ + if (ip6cp->ip6c_m->m_pkthdr.len < + (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) { + return; + } - /* Copy out the port numbers and the verification tag. */ - memset(&sh, 0, sizeof(sh)); - m_copydata(ip6cp->ip6c_m, - ip6cp->ip6c_off, - sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), - (caddr_t)&sh); - memset(&src, 0, sizeof(struct sockaddr_in6)); - src.sin6_family = AF_INET6; - src.sin6_len = sizeof(struct sockaddr_in6); - src.sin6_port = sh.src_port; - src.sin6_addr = ip6cp->ip6c_ip6->ip6_src; - if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) { - return; - } - memset(&dst, 0, sizeof(struct sockaddr_in6)); - dst.sin6_family = AF_INET6; - dst.sin6_len = sizeof(struct sockaddr_in6); - dst.sin6_port = sh.dest_port; - dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst; - if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) { - return; - } - inp = NULL; - net = NULL; - stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst, - (struct sockaddr *)&src, - &inp, &net, 1, SCTP_DEFAULT_VRFID); - if ((stcb != NULL) && - (net != NULL) && - (inp != NULL)) { - /* Check the verification tag */ - if (ntohl(sh.v_tag) != 0) { + /* Copy out the port numbers and the verification tag. */ + memset(&sh, 0, sizeof(sh)); + m_copydata(ip6cp->ip6c_m, + ip6cp->ip6c_off, + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), + (caddr_t)&sh); + memset(&src, 0, sizeof(struct sockaddr_in6)); + src.sin6_family = AF_INET6; + src.sin6_len = sizeof(struct sockaddr_in6); + src.sin6_port = sh.src_port; + src.sin6_addr = ip6cp->ip6c_ip6->ip6_src; + if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) { + return; + } + memset(&dst, 0, sizeof(struct sockaddr_in6)); + dst.sin6_family = AF_INET6; + dst.sin6_len = sizeof(struct sockaddr_in6); + dst.sin6_port = sh.dest_port; + dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst; + if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) { + return; + } + inp = NULL; + net = NULL; + stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst, + (struct sockaddr *)&src, + &inp, &net, 1, SCTP_DEFAULT_VRFID); + if ((stcb != NULL) && + (net != NULL) && + (inp != NULL)) { + /* Check the verification tag */ + if (ntohl(sh.v_tag) != 0) { + /* + * This must be the verification tag used + * for sending out packets. We don't + * consider packets reflecting the + * verification tag. + */ + if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) { + SCTP_TCB_UNLOCK(stcb); + return; + } + } else { + if (ip6cp->ip6c_m->m_pkthdr.len >= + ip6cp->ip6c_off + sizeof(struct sctphdr) + + sizeof(struct sctp_chunkhdr) + + offsetof(struct sctp_init, a_rwnd)) { /* - * This must be the verification tag used - * for sending out packets. We don't - * consider packets reflecting the - * verification tag. + * In this case we can check if we + * got an INIT chunk and if the + * initiate tag matches. */ - if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) { + uint32_t initiate_tag; + uint8_t chunk_type; + + m_copydata(ip6cp->ip6c_m, + ip6cp->ip6c_off + + sizeof(struct sctphdr), + sizeof(uint8_t), + (caddr_t)&chunk_type); + m_copydata(ip6cp->ip6c_m, + ip6cp->ip6c_off + + sizeof(struct sctphdr) + + sizeof(struct sctp_chunkhdr), + sizeof(uint32_t), + (caddr_t)&initiate_tag); + if ((chunk_type != SCTP_INITIATION) || + (ntohl(initiate_tag) != stcb->asoc.my_vtag)) { SCTP_TCB_UNLOCK(stcb); return; } } else { - if (ip6cp->ip6c_m->m_pkthdr.len >= - ip6cp->ip6c_off + sizeof(struct sctphdr) + - sizeof(struct sctp_chunkhdr) + - offsetof(struct sctp_init, a_rwnd)) { - /* - * In this case we can check if we - * got an INIT chunk and if the - * initiate tag matches. - */ - uint32_t initiate_tag; - uint8_t chunk_type; - - m_copydata(ip6cp->ip6c_m, - ip6cp->ip6c_off + - sizeof(struct sctphdr), - sizeof(uint8_t), - (caddr_t)&chunk_type); - m_copydata(ip6cp->ip6c_m, - ip6cp->ip6c_off + - sizeof(struct sctphdr) + - sizeof(struct sctp_chunkhdr), - sizeof(uint32_t), - (caddr_t)&initiate_tag); - if ((chunk_type != SCTP_INITIATION) || - (ntohl(initiate_tag) != stcb->asoc.my_vtag)) { - SCTP_TCB_UNLOCK(stcb); - return; - } - } else { - SCTP_TCB_UNLOCK(stcb); - return; - } - } - sctp6_notify(inp, stcb, net, - ip6cp->ip6c_icmp6->icmp6_type, - ip6cp->ip6c_icmp6->icmp6_code, - ntohl(ip6cp->ip6c_icmp6->icmp6_mtu)); - } else { - if ((stcb == NULL) && (inp != NULL)) { - /* reduce inp's ref-count */ - SCTP_INP_WLOCK(inp); - SCTP_INP_DECR_REF(inp); - SCTP_INP_WUNLOCK(inp); - } - if (stcb) { SCTP_TCB_UNLOCK(stcb); + return; } } + sctp6_notify(inp, stcb, net, + ip6cp->ip6c_icmp6->icmp6_type, + ip6cp->ip6c_icmp6->icmp6_code, + ntohl(ip6cp->ip6c_icmp6->icmp6_mtu)); + } else { + if ((stcb == NULL) && (inp != NULL)) { + /* reduce inp's ref-count */ + SCTP_INP_WLOCK(inp); + SCTP_INP_DECR_REF(inp); + SCTP_INP_WUNLOCK(inp); + } + if (stcb) { + SCTP_TCB_UNLOCK(stcb); + } } } diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index f7f737f7e051..f387724ad997 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -553,8 +553,8 @@ udp6_common_ctlinput(int cmd, struct sockaddr_in6 *sin6, struct udphdr uh; struct ip6_hdr *ip6; struct mbuf *m; + struct inpcb *inp; int off = 0; - const struct sockaddr_in6 *sa6_src = NULL; void *cmdarg; struct inpcb *(*notify)(struct inpcb *, int) = udp_notify; struct udp_portonly { @@ -562,70 +562,38 @@ udp6_common_ctlinput(int cmd, struct sockaddr_in6 *sin6, u_int16_t uh_dport; } *uhp; - if ((unsigned)cmd >= PRC_NCMDS) + if (inet6ctlerrmap[cmd] == 0) return; - if (PRC_IS_REDIRECT(cmd)) - notify = in6_rtchange, ip6cp = NULL; - else if (cmd == PRC_HOSTDEAD) - ip6cp = NULL; - else if (inet6ctlerrmap[cmd] == 0) + + m = ip6cp->ip6c_m; + ip6 = ip6cp->ip6c_ip6; + off = ip6cp->ip6c_off; + cmdarg = ip6cp->ip6c_cmdarg; + + /* Check if we can safely examine src and dst ports. */ + if (m->m_pkthdr.len < off + sizeof(*uhp)) return; - /* if the parameter is from icmp6, decode it. */ - if (ip6cp != NULL) { - m = ip6cp->ip6c_m; - ip6 = ip6cp->ip6c_ip6; - off = ip6cp->ip6c_off; - cmdarg = ip6cp->ip6c_cmdarg; - sa6_src = ip6cp->ip6c_src; - } else { - m = NULL; - ip6 = NULL; - cmdarg = NULL; - sa6_src = &sa6_any; - } + bzero(&uh, sizeof(uh)); + m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); - if (ip6) { - /* - * XXX: We assume that when IPV6 is non NULL, - * M and OFF are valid. - */ + /* Check to see if its tunneled */ + inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_dst, uh.uh_dport, + &ip6->ip6_src, uh.uh_sport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, + m->m_pkthdr.rcvif, m); + if (inp != NULL) { + struct udpcb *up; + udp_tun_icmp_t *func; - /* Check if we can safely examine src and dst ports. */ - if (m->m_pkthdr.len < off + sizeof(*uhp)) - return; - - bzero(&uh, sizeof(uh)); - m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh); - - if (!PRC_IS_REDIRECT(cmd)) { - /* Check to see if its tunneled */ - struct inpcb *inp; - inp = in6_pcblookup_mbuf(pcbinfo, &ip6->ip6_dst, - uh.uh_dport, &ip6->ip6_src, uh.uh_sport, - INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, - m->m_pkthdr.rcvif, m); - if (inp != NULL) { - struct udpcb *up; - - up = intoudpcb(inp); - if (up->u_icmp_func) { - /* Yes it is. */ - INP_RUNLOCK(inp); - (*up->u_icmp_func)(cmd, (struct sockaddr *)ip6cp->ip6c_src, - ip6cp, up->u_tun_ctx); - return; - } else { - /* Can't find it. */ - INP_RUNLOCK(inp); - } - } - } - in6_pcbnotify(pcbinfo, sin6, uh.uh_dport, ip6cp->ip6c_src, - uh.uh_sport, cmd, cmdarg, notify); - } else - in6_pcbnotify(pcbinfo, sin6, 0, sa6_src, 0, cmd, cmdarg, - notify); + up = intoudpcb(inp); + func = up->u_icmp_func; + INP_RUNLOCK(inp); + if (func != NULL) + func(cmd, (struct sockaddr *)ip6cp->ip6c_src, ip6cp, + up->u_tun_ctx); + } + in6_pcbnotify(pcbinfo, sin6, uh.uh_dport, ip6cp->ip6c_src, + uh.uh_sport, cmd, cmdarg, notify); } static void