Date: Tue, 12 Apr 2016 21:40:54 +0000 (UTC) From: Michael Tuexen <tuexen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r297880 - head/sys/netinet Message-ID: <201604122140.u3CLesZW053757@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tuexen Date: Tue Apr 12 21:40:54 2016 New Revision: 297880 URL: https://svnweb.freebsd.org/changeset/base/297880 Log: Refactor the handling of ICMP/IPv4 packets for SCTP/IPv4. This cleansup the code and prepares upcoming handling of ICMP/IPv4 packets for SCTP/UDP/IPv4 packets. IPv6 changes will follow... MFC after: 3 days Modified: head/sys/netinet/sctp_usrreq.c Modified: head/sys/netinet/sctp_usrreq.c ============================================================================== --- head/sys/netinet/sctp_usrreq.c Tue Apr 12 21:34:04 2016 (r297879) +++ head/sys/netinet/sctp_usrreq.c Tue Apr 12 21:40:54 2016 (r297880) @@ -144,102 +144,33 @@ sctp_pathmtu_adjustment(struct sctp_tcb #ifdef INET static void -sctp_notify_mbuf(struct sctp_inpcb *inp, - struct sctp_tcb *stcb, - struct sctp_nets *net, - struct ip *ip) -{ - struct icmp *icmph; - int totsz, tmr_stopped = 0; - uint16_t nxtsz; - - /* protection */ - if ((inp == NULL) || (stcb == NULL) || (net == NULL) || (ip == NULL)) { - if (stcb != NULL) { - SCTP_TCB_UNLOCK(stcb); - } - return; - } - icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) - - sizeof(struct ip))); - if (icmph->icmp_type != ICMP_UNREACH) { - /* We only care about unreachable */ - SCTP_TCB_UNLOCK(stcb); - return; - } - if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) { - /* not a unreachable message due to frag. */ - SCTP_TCB_UNLOCK(stcb); - return; - } - totsz = ntohs(ip->ip_len); - - nxtsz = ntohs(icmph->icmp_nextmtu); - if (nxtsz == 0) { - /* - * old type router that does not tell us what the next size - * mtu is. Rats we will have to guess (in a educated fashion - * of course) - */ - nxtsz = sctp_get_prev_mtu(totsz); - } - /* Stop any PMTU timer */ - if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { - tmr_stopped = 1; - sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, - SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1); - } - /* Adjust destination size limit */ - if (net->mtu > nxtsz) { - net->mtu = nxtsz; - if (net->port) { - net->mtu -= sizeof(struct udphdr); - } - } - /* now what about the ep? */ - if (stcb->asoc.smallest_mtu > nxtsz) { - sctp_pathmtu_adjustment(stcb, nxtsz); - } - if (tmr_stopped) - sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); - - SCTP_TCB_UNLOCK(stcb); -} - -static void sctp_notify(struct sctp_inpcb *inp, - struct ip *ip, - struct sockaddr *to, struct sctp_tcb *stcb, - struct sctp_nets *net) + struct sctp_nets *net, + uint8_t icmp_type, + uint8_t icmp_code, + uint16_t ip_len, + uint16_t next_mtu) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif - struct icmp *icmph; + int timer_stopped; - /* protection */ - if ((inp == NULL) || (stcb == NULL) || (net == NULL) || (to == NULL)) { - if (stcb) - SCTP_TCB_UNLOCK(stcb); - return; - } - icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) - - sizeof(struct ip))); - if (icmph->icmp_type != ICMP_UNREACH) { + if (icmp_type != ICMP_UNREACH) { /* We only care about unreachable */ SCTP_TCB_UNLOCK(stcb); return; } - if ((icmph->icmp_code == ICMP_UNREACH_NET) || - (icmph->icmp_code == ICMP_UNREACH_HOST) || - (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) || - (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) || - (icmph->icmp_code == ICMP_UNREACH_ISOLATED) || - (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) || - (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) || - (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) { + if ((icmp_code == ICMP_UNREACH_NET) || + (icmp_code == ICMP_UNREACH_HOST) || + (icmp_code == ICMP_UNREACH_NET_UNKNOWN) || + (icmp_code == ICMP_UNREACH_HOST_UNKNOWN) || + (icmp_code == ICMP_UNREACH_ISOLATED) || + (icmp_code == ICMP_UNREACH_NET_PROHIB) || + (icmp_code == ICMP_UNREACH_HOST_PROHIB) || + (icmp_code == ICMP_UNREACH_FILTER_PROHIB)) { /* * Hmm reachablity problems we must examine closely. If its @@ -248,7 +179,7 @@ sctp_notify(struct sctp_inpcb *inp, * it a OOTB abort. */ if (net->dest_state & SCTP_ADDR_REACHABLE) { - /* Ok that destination is NOT reachable */ + /* OK, that destination is NOT reachable. */ net->dest_state &= ~SCTP_ADDR_REACHABLE; net->dest_state &= ~SCTP_ADDR_PF; sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, @@ -256,8 +187,8 @@ sctp_notify(struct sctp_inpcb *inp, (void *)net, SCTP_SO_NOT_LOCKED); } SCTP_TCB_UNLOCK(stcb); - } else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) || - (icmph->icmp_code == ICMP_UNREACH_PORT)) { + } else if ((icmp_code == ICMP_UNREACH_PROTOCOL) || + (icmp_code == ICMP_UNREACH_PORT)) { /* * Here the peer is either playing tricks on us, including * an address that belongs to someone who does not support @@ -281,19 +212,51 @@ sctp_notify(struct sctp_inpcb *inp, /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */ #endif /* no need to unlock here, since the TCB is gone */ + } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) { + /* Find the next (smaller) MTU */ + if (next_mtu == 0) { + /* + * Old type router that does not tell us what the + * next MTU is. Rats we will have to guess (in a + * educated fashion of course). + */ + next_mtu = sctp_get_prev_mtu(ip_len); + } + /* Stop the PMTU timer. */ + if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { + timer_stopped = 1; + sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, + SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1); + } else { + timer_stopped = 0; + } + /* Update the path MTU. */ + if (net->mtu > next_mtu) { + net->mtu = next_mtu; + if (net->port) { + net->mtu -= sizeof(struct udphdr); + } + } + /* Update the association MTU */ + if (stcb->asoc.smallest_mtu > next_mtu) { + sctp_pathmtu_adjustment(stcb, next_mtu); + } + /* Finally, start the PMTU timer if it was running before. */ + if (timer_stopped) { + sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); + } + SCTP_TCB_UNLOCK(stcb); } else { SCTP_TCB_UNLOCK(stcb); } } -#endif - -#ifdef INET void sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) { struct ip *ip = vip; struct sctphdr *sh; + struct icmp *icmph; uint32_t vrf_id; /* FIX, for non-bsd is this right? */ @@ -313,6 +276,9 @@ sctp_ctlinput(int cmd, struct sockaddr * struct sctp_nets *net = NULL; struct sockaddr_in to, from; + icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) - + sizeof(struct ip))); + sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2)); bzero(&to, sizeof(to)); bzero(&from, sizeof(from)); @@ -322,7 +288,6 @@ sctp_ctlinput(int cmd, struct sockaddr * from.sin_addr = ip->ip_src; to.sin_port = sh->dest_port; to.sin_addr = ip->ip_dst; - /* * 'to' holds the dest of the packet that failed to be sent. * 'from' holds our local endpoint address. Thus we reverse @@ -332,6 +297,7 @@ sctp_ctlinput(int cmd, struct sockaddr * (struct sockaddr *)&from, &inp, &net, 1, vrf_id); if ((stcb != NULL) && + (net != NULL) && (inp != NULL) && (inp->sctp_socket != NULL)) { /* Check the verification tag */ @@ -342,7 +308,7 @@ sctp_ctlinput(int cmd, struct sockaddr * * consider packets reflecting the * verification tag. */ - if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) { + if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) { SCTP_TCB_UNLOCK(stcb); return; } @@ -355,14 +321,11 @@ sctp_ctlinput(int cmd, struct sockaddr * SCTP_TCB_UNLOCK(stcb); return; } - if (cmd != PRC_MSGSIZE) { - sctp_notify(inp, ip, - (struct sockaddr *)&to, stcb, - net); - } else { - /* handle possible ICMP size messages */ - sctp_notify_mbuf(inp, stcb, net, ip); - } + sctp_notify(inp, stcb, net, + icmph->icmp_type, + icmph->icmp_code, + ntohs(ip->ip_len), + ntohs(icmph->icmp_nextmtu)); } else { if ((stcb == NULL) && (inp != NULL)) { /* reduce ref-count */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604122140.u3CLesZW053757>