Page MenuHomeFreeBSD

D36729.diff
No OneTemporary

D36729.diff

diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -260,10 +260,9 @@
}
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 @@
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
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2866,39 +2866,27 @@
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 @@
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 @@
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 @@
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
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -746,53 +746,34 @@
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
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -256,124 +256,112 @@
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
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -553,8 +553,8 @@
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 @@
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

File Metadata

Mime Type
text/plain
Expires
Mon, Apr 21, 2:34 AM (15 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17658503
Default Alt Text
D36729.diff (20 KB)

Event Timeline