svn commit: r297880 - head/sys/netinet
Michael Tuexen
tuexen at FreeBSD.org
Tue Apr 12 21:40:55 UTC 2016
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 */
More information about the svn-src-all
mailing list