diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -701,6 +701,7 @@ struct in6_multi; # endif void icmp6_paramerror(struct mbuf *, int); +int icmp6_errmap(const struct icmp6_hdr *); void icmp6_error(struct mbuf *, int, int, int); void icmp6_error2(struct mbuf *, int, int, int, struct ifnet *); int icmp6_input(struct mbuf **, int *, int); diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -100,8 +100,6 @@ #define IN_LNAOF(in, ifa) \ ((ntohl((in).s_addr) & ~((struct in_ifaddr *)(ifa)->ia_subnetmask)) -extern u_char inetctlerrmap[]; - #define LLTABLE(ifp) \ ((struct in_ifinfo *)(ifp)->if_afdata[AF_INET])->ii_llt /* diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -216,6 +216,7 @@ (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) #ifdef _KERNEL +int icmp_errmap(const struct icmp *); void icmp_error(struct mbuf *, int, int, uint32_t, int); int icmp_input(struct mbuf **, int *, int); int ip_next_mtu(int, int); diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -403,6 +403,55 @@ m_freem(n); } +int +icmp_errmap(const struct icmp *icp) +{ + + switch (icp->icmp_type) { + case ICMP_UNREACH: + switch (icp->icmp_code) { + case ICMP_UNREACH_NET: + case ICMP_UNREACH_HOST: + case ICMP_UNREACH_SRCFAIL: + case ICMP_UNREACH_NET_UNKNOWN: + case ICMP_UNREACH_HOST_UNKNOWN: + case ICMP_UNREACH_ISOLATED: + case ICMP_UNREACH_TOSNET: + case ICMP_UNREACH_TOSHOST: + case ICMP_UNREACH_HOST_PRECEDENCE: + case ICMP_UNREACH_PRECEDENCE_CUTOFF: + return (EHOSTUNREACH); + case ICMP_UNREACH_NEEDFRAG: + return (EMSGSIZE); + case ICMP_UNREACH_PROTOCOL: + case ICMP_UNREACH_PORT: + case ICMP_UNREACH_NET_PROHIB: + case ICMP_UNREACH_HOST_PROHIB: + case ICMP_UNREACH_FILTER_PROHIB: + return (ECONNREFUSED); + default: + return (0); + } + case ICMP_TIMXCEED: + switch (icp->icmp_code) { + case ICMP_TIMXCEED_INTRANS: + return (EHOSTUNREACH); + default: + return (0); + } + case ICMP_PARAMPROB: + switch (icp->icmp_code) { + case ICMP_PARAMPROB_ERRATPTR: + case ICMP_PARAMPROB_OPTABSENT: + return (ENOPROTOOPT); + default: + return (0); + } + default: + return (0); + } +} + /* * Process a received ICMP message. */ @@ -484,56 +533,21 @@ code = icp->icmp_code; switch (icp->icmp_type) { case ICMP_UNREACH: - switch (code) { - case ICMP_UNREACH_NET: - case ICMP_UNREACH_HOST: - case ICMP_UNREACH_SRCFAIL: - case ICMP_UNREACH_NET_UNKNOWN: - case ICMP_UNREACH_HOST_UNKNOWN: - case ICMP_UNREACH_ISOLATED: - case ICMP_UNREACH_TOSNET: - case ICMP_UNREACH_TOSHOST: - case ICMP_UNREACH_HOST_PRECEDENCE: - case ICMP_UNREACH_PRECEDENCE_CUTOFF: - code = PRC_UNREACH_NET; - break; - - case ICMP_UNREACH_NEEDFRAG: - code = PRC_MSGSIZE; - break; - - /* - * RFC 1122, Sections 3.2.2.1 and 4.2.3.9. - * Treat subcodes 2,3 as immediate RST - */ - case ICMP_UNREACH_PROTOCOL: - code = PRC_UNREACH_PROTOCOL; - break; - case ICMP_UNREACH_PORT: - code = PRC_UNREACH_PORT; - break; - - case ICMP_UNREACH_NET_PROHIB: - case ICMP_UNREACH_HOST_PROHIB: - case ICMP_UNREACH_FILTER_PROHIB: - code = PRC_UNREACH_ADMIN_PROHIB; - break; - - default: - goto badcode; - } - goto deliver; + if (code > ICMP_UNREACH_PRECEDENCE_CUTOFF) + goto badcode; + else + goto deliver; case ICMP_TIMXCEED: - if (code > 1) + if (code > ICMP_TIMXCEED_REASS) goto badcode; - code += PRC_TIMXCEED_INTRANS; - goto deliver; + else + goto deliver; case ICMP_PARAMPROB: - if (code > 1) + if (code > ICMP_PARAMPROB_LENGTH) goto badcode; - code = PRC_PARAMPROB; + deliver: /* * Problem with datagram; advise higher level routines. @@ -553,7 +567,6 @@ if (icmpprintfs) printf("deliver to protocol %d\n", icp->icmp_ip.ip_p); #endif - icmpsrc.sin_addr = icp->icmp_ip.ip_dst; /* * XXX if the packet contains [IPv4 AH TCP], we can't make a * notification to TCP layer. @@ -576,8 +589,7 @@ * ICMP_ADVLENPREF. See its definition in ip_icmp.h. */ if (ip_ctlprotox[icp->icmp_ip.ip_p] != NULL) - ip_ctlprotox[icp->icmp_ip.ip_p](code, &icmpsrc, - &icp->icmp_ip); + ip_ctlprotox[icp->icmp_ip.ip_p](icp); break; badcode: diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -873,23 +873,6 @@ return (ENOENT); } -/* (x) - issued by icmp_input() */ -u_char inetctlerrmap[PRC_NCMDS] = { - [PRC_MSGSIZE] = EMSGSIZE, /* (x) */ - [PRC_HOSTDEAD] = EHOSTDOWN, - [PRC_HOSTUNREACH] = EHOSTUNREACH, - [PRC_UNREACH_NET] = EHOSTUNREACH, /* (x) */ - [PRC_UNREACH_HOST] = EHOSTUNREACH, - [PRC_UNREACH_PROTOCOL] = ECONNREFUSED, /* (x) */ - [PRC_UNREACH_PORT] = ECONNREFUSED, /* (x) */ - [12] = EMSGSIZE, - [PRC_UNREACH_SRCFAIL] = EHOSTUNREACH, - [PRC_TIMXCEED_INTRANS] = EHOSTUNREACH, /* (x) */ - [PRC_TIMXCEED_REASS] = 0, /* (x) */ - [PRC_PARAMPROB] = ENOPROTOOPT, /* (x) */ - [PRC_UNREACH_ADMIN_PROHIB] = ECONNREFUSED, /* (x) */ -}; - /* * Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -238,7 +238,8 @@ extern int (*rsvp_input_p)(struct mbuf **, int *, int); typedef int ipproto_input_t(struct mbuf **, int *, int); -typedef void ipproto_ctlinput_t(int, struct sockaddr_in *, struct ip *); +struct icmp; +typedef void ipproto_ctlinput_t(struct icmp *); int ipproto_register(uint8_t, ipproto_input_t, ipproto_ctlinput_t); int ipproto_unregister(uint8_t); #define IPPROTO_REGISTER(prot, input, ctl) do { \ diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -804,17 +804,12 @@ } void -rip_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) +rip_ctlinput(struct icmp *icmp) { - - switch (cmd) { #if defined(IPSEC) || defined(IPSEC_SUPPORT) - case PRC_MSGSIZE: - if (IPSEC_ENABLED(ipv4)) - IPSEC_CTLINPUT(ipv4, cmd, (struct sockaddr *)sin, ip); - break; + if (IPSEC_ENABLED(ipv4)) + IPSEC_CTLINPUT(ipv4, icmp); #endif - } } static int 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,23 +260,21 @@ } void -sctp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *inner_ip) +sctp_ctlinput(struct icmp *icmp) { - struct ip *outer_ip; + struct ip *inner_ip, *outer_ip; struct sctphdr *sh; - struct icmp *icmp; struct sctp_inpcb *inp; struct sctp_tcb *stcb; struct sctp_nets *net; struct sctp_init_chunk *ch; struct sockaddr_in src, dst; - if (inetctlerrmap[cmd] == 0) + if (icmp_errmap(icmp) == 0) return; - icmp = (struct icmp *)((caddr_t)inner_ip - - (sizeof(struct icmp) - sizeof(struct ip))); outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); + inner_ip = &icmp->icmp_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; diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h --- a/sys/netinet/sctp_var.h +++ b/sys/netinet/sctp_var.h @@ -322,7 +322,7 @@ void sctp_close(struct socket *so); int sctp_disconnect(struct socket *so); -void sctp_ctlinput(int, struct sockaddr_in *, struct ip *); +ipproto_ctlinput_t sctp_ctlinput; int sctp_ctloutput(struct socket *, struct sockopt *); void sctp_input_with_port(struct mbuf *, int, uint16_t); int sctp_input(struct mbuf **, int *, int); diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c --- a/sys/netinet/sctputil.c +++ b/sys/netinet/sctputil.c @@ -7190,11 +7190,11 @@ #ifdef INET static void -sctp_recv_icmp_tunneled_packet(int cmd, struct sockaddr *sa, void *vip, void *ctx SCTP_UNUSED) +sctp_recv_icmp_tunneled_packet(udp_tun_icmp_param_t param) { + struct icmp *icmp = param.icmp; struct ip *outer_ip, *inner_ip; struct sctphdr *sh; - struct icmp *icmp; struct udphdr *udp; struct sctp_inpcb *inp; struct sctp_tcb *stcb; @@ -7203,9 +7203,7 @@ struct sockaddr_in src, dst; uint8_t type, code; - inner_ip = (struct ip *)vip; - icmp = (struct icmp *)((caddr_t)inner_ip - - (sizeof(struct icmp) - sizeof(struct ip))); + inner_ip = &icmp->icmp_ip; outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); if (ntohs(outer_ip->ip_len) < sizeof(struct ip) + 8 + (inner_ip->ip_hl << 2) + sizeof(struct udphdr) + 8) { @@ -7300,9 +7298,9 @@ #ifdef INET6 static void -sctp_recv_icmp6_tunneled_packet(int cmd, struct sockaddr *sa, void *d, void *ctx SCTP_UNUSED) +sctp_recv_icmp6_tunneled_packet(udp_tun_icmp_param_t param) { - struct ip6ctlparam *ip6cp; + struct ip6ctlparam *ip6cp = param.ip6cp; struct sctp_inpcb *inp; struct sctp_tcb *stcb; struct sctp_nets *net; @@ -7311,7 +7309,6 @@ struct sockaddr_in6 src, dst; uint8_t type, code; - ip6cp = (struct ip6ctlparam *)d; /* * XXX: We assume that when IPV6 is non NULL, M and OFF are valid. */ 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 @@ -2842,38 +2842,44 @@ } static void -tcp_ctlinput_with_port(int cmd, struct sockaddr_in *sin, struct ip *ip, - uint16_t port) +tcp_ctlinput_with_port(struct icmp *icp, uint16_t port) { + struct ip *ip; struct tcphdr *th; struct inpcb *inp; struct tcpcb *tp; - struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify; - struct icmp *icp; + struct inpcb *(*notify)(struct inpcb *, int); struct in_conninfo inc; tcp_seq icmp_tcp_seq; - int mtu; + int errno, mtu; - switch (cmd) { - case PRC_MSGSIZE: + errno = icmp_errmap(icp); + switch (errno) { + case 0: + return; + case EMSGSIZE: notify = tcp_mtudisc_notify; break; - case PRC_UNREACH_PORT: - case PRC_UNREACH_PROTOCOL: - case PRC_TIMXCEED_INTRANS: - case PRC_UNREACH_ADMIN_PROHIB: + case ECONNREFUSED: if (V_icmp_may_rst) notify = tcp_drop_syn_sent; + else + notify = tcp_notify; break; + case EHOSTUNREACH: + if (V_icmp_may_rst && icp->icmp_type == ICMP_TIMXCEED) + notify = tcp_drop_syn_sent; + else + notify = tcp_notify; + break; + default: + notify = tcp_notify; } - if (inetctlerrmap[cmd] == 0) - return; - - icp = (struct icmp *)((caddr_t)ip - offsetof(struct icmp, icmp_ip)); + ip = &icp->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, + inp = in_pcblookup(&V_tcbinfo, ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL); if (inp != NULL) { if (!(inp->inp_flags & INP_TIMEWAIT) && @@ -2881,7 +2887,7 @@ !(inp->inp_socket == NULL)) { tp = intotcpcb(inp); #ifdef TCP_OFFLOAD - if (tp->t_flags & TF_TOE && cmd == PRC_MSGSIZE) { + if (tp->t_flags & TF_TOE && errno == EMSGSIZE) { /* * MTU discovery for offloaded connections. Let * the TOE driver verify seq# and process it. @@ -2896,7 +2902,7 @@ } if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { - if (cmd == PRC_MSGSIZE) { + if (errno == EMSGSIZE) { /* * MTU discovery: we got a needfrag and * will potentially try a lower MTU. @@ -2910,22 +2916,21 @@ if (mtu < tp->t_maxseg + sizeof(struct tcpiphdr)) { bzero(&inc, sizeof(inc)); - inc.inc_faddr = sin->sin_addr; + inc.inc_faddr = ip->ip_dst; inc.inc_fibnum = inp->inp_inc.inc_fibnum; tcp_hc_updatemtu(&inc, mtu); inp = tcp_mtudisc(inp, mtu); } } else - inp = (*notify)(inp, - inetctlerrmap[cmd]); + inp = (*notify)(inp, errno); } } } else { bzero(&inc, sizeof(inc)); inc.inc_fport = th->th_dport; inc.inc_lport = th->th_sport; - inc.inc_faddr = sin->sin_addr; + inc.inc_faddr = ip->ip_dst; inc.inc_laddr = ip->ip_src; syncache_unreach(&inc, icmp_tcp_seq, port); } @@ -2935,26 +2940,24 @@ } static void -tcp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) +tcp_ctlinput(struct icmp *icmp) { - tcp_ctlinput_with_port(cmd, sin, ip, htons(0)); + tcp_ctlinput_with_port(icmp, htons(0)); } static void -tcp_ctlinput_viaudp(int cmd, struct sockaddr *sa, void *vip, void *unused) +tcp_ctlinput_viaudp(udp_tun_icmp_param_t param) { /* Its a tunneled TCP over UDP icmp */ + struct icmp *icmp = param.icmp; struct ip *outer_ip, *inner_ip; - struct icmp *icmp; struct udphdr *udp; struct tcphdr *th, ttemp; int i_hlen, o_len; uint16_t port; - inner_ip = (struct ip *)vip; - icmp = (struct icmp *)((caddr_t)inner_ip - - (sizeof(struct icmp) - sizeof(struct ip))); outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip)); + inner_ip = &icmp->icmp_ip; i_hlen = inner_ip->ip_hl << 2; o_len = ntohs(outer_ip->ip_len); if (o_len < @@ -2975,7 +2978,7 @@ o_len -= sizeof(struct udphdr); outer_ip->ip_len = htons(o_len); /* Now call in to the normal handling code */ - tcp_ctlinput_with_port(cmd, (struct sockaddr_in *)sa, vip, port); + tcp_ctlinput_with_port(icmp, port); } #endif /* INET */ @@ -2995,11 +2998,10 @@ } static void -tcp6_ctlinput_with_port(int cmd, struct sockaddr_in6 *sin6, - struct ip6ctlparam *ip6cp, uint16_t port) +tcp6_ctlinput_with_port(struct ip6ctlparam *ip6cp, uint16_t port) { struct in6_addr *dst; - struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify; + struct inpcb *(*notify)(struct inpcb *, int); struct ip6_hdr *ip6; struct mbuf *m; struct inpcb *inp; @@ -3013,29 +3015,51 @@ tcp_seq icmp_tcp_seq; unsigned int mtu; unsigned int off; + int errno; icmp6 = ip6cp->ip6c_icmp6; m = ip6cp->ip6c_m; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; - dst = ip6cp->ip6c_finaldst; + dst = &ip6cp->ip6c_finaldst->sin6_addr; - switch (cmd) { - case PRC_MSGSIZE: + errno = icmp6_errmap(icmp6); + switch (errno) { + case 0: + return; + case EMSGSIZE: notify = tcp_mtudisc_notify; break; - case PRC_UNREACH_ADMIN_PROHIB: - case PRC_UNREACH_PORT: - case PRC_UNREACH_PROTOCOL: - case PRC_TIMXCEED_INTRANS: + case ECONNREFUSED: if (V_icmp_may_rst) notify = tcp_drop_syn_sent; + else + notify = tcp_notify; + break; + case EHOSTUNREACH: + /* + * There are only four ICMPs that may reset connection: + * - administratively prohibited + * - port unreachable + * - time exceeded in transit + * - unknown next header + */ + if (V_icmp_may_rst && + ((icmp6->icmp6_type == ICMP6_DST_UNREACH && + (icmp6->icmp6_code == ICMP6_DST_UNREACH_ADMIN || + icmp6->icmp6_code == ICMP6_DST_UNREACH_NOPORT)) || + (icmp6->icmp6_type == ICMP6_TIME_EXCEEDED && + icmp6->icmp6_code == ICMP6_TIME_EXCEED_TRANSIT) || + (icmp6->icmp6_type == ICMP6_PARAM_PROB && + icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER))) + notify = tcp_drop_syn_sent; + else + notify = tcp_notify; break; + default: + notify = tcp_notify; } - if (inet6ctlerrmap[cmd] == 0) - return; - /* Check if we can safely get the ports from the tcp hdr */ if (m == NULL || (m->m_pkthdr.len < @@ -3057,7 +3081,7 @@ !(inp->inp_socket == NULL)) { tp = intotcpcb(inp); #ifdef TCP_OFFLOAD - if (tp->t_flags & TF_TOE && cmd == PRC_MSGSIZE) { + if (tp->t_flags & TF_TOE && errno == EMSGSIZE) { /* MTU discovery for offloaded connections. */ mtu = tcp6_next_pmtu(icmp6); tcp_offload_pmtu_update(tp, icmp_tcp_seq, mtu); @@ -3069,7 +3093,7 @@ } if (SEQ_GEQ(ntohl(icmp_tcp_seq), tp->snd_una) && SEQ_LT(ntohl(icmp_tcp_seq), tp->snd_max)) { - if (cmd == PRC_MSGSIZE) { + if (errno == EMSGSIZE) { /* * MTU discovery: * If we got a needfrag set the MTU @@ -3097,8 +3121,7 @@ ICMP6STAT_INC(icp6s_pmtuchg); } } else - inp = (*notify)(inp, - inet6ctlerrmap[cmd]); + inp = (*notify)(inp, errno); } } } else { @@ -3117,20 +3140,19 @@ } static void -tcp6_ctlinput(int cmd, struct sockaddr_in6 *sin6, struct ip6ctlparam *ctl) +tcp6_ctlinput(struct ip6ctlparam *ctl) { - tcp6_ctlinput_with_port(cmd, sin6, ctl, htons(0)); + tcp6_ctlinput_with_port(ctl, htons(0)); } static void -tcp6_ctlinput_viaudp(int cmd, struct sockaddr *sa, void *d, void *unused) +tcp6_ctlinput_viaudp(udp_tun_icmp_param_t param) { - struct ip6ctlparam *ip6cp; + struct ip6ctlparam *ip6cp = param.ip6cp; struct mbuf *m; struct udphdr *udp; uint16_t port; - ip6cp = (struct ip6ctlparam *)d; m = m_pulldown(ip6cp->ip6c_m, ip6cp->ip6c_off, sizeof(struct udphdr), NULL); if (m == NULL) { return; @@ -3145,7 +3167,7 @@ ip6cp->ip6c_m->m_pkthdr.len -= sizeof(struct udphdr); } /* Now call in to the normal handling code */ - tcp6_ctlinput_with_port(cmd, (struct sockaddr_in6 *)sa, ip6cp, port); + tcp6_ctlinput_with_port(ip6cp, port); } #endif /* INET6 */ 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 @@ -740,54 +740,52 @@ #ifdef INET static void -udp_common_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip, - struct inpcbinfo *pcbinfo) +udp_common_ctlinput(struct icmp *icmp, struct inpcbinfo *pcbinfo) { + struct ip *ip = &icmp->icmp_ip; struct udphdr *uh; struct inpcb *inp; - if (inetctlerrmap[cmd] == 0) + if (icmp_errmap(icmp) == 0) return; uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); - inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, ip->ip_src, + inp = in_pcblookup(pcbinfo, ip->ip_dst, 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]); + udp_notify(inp, icmp_errmap(icmp)); INP_WUNLOCK(inp); } else { - inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, + inp = in_pcblookup(pcbinfo, ip->ip_dst, 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); + func(icmp); } } } static void -udp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) +udp_ctlinput(struct icmp *icmp) { - return (udp_common_ctlinput(cmd, sin, ip, &V_udbinfo)); + return (udp_common_ctlinput(icmp, &V_udbinfo)); } static void -udplite_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) +udplite_ctlinput(struct icmp *icmp) { - return (udp_common_ctlinput(cmd, sin, ip, &V_ulitecbinfo)); + return (udp_common_ctlinput(icmp, &V_ulitecbinfo)); } #endif /* INET */ diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -64,7 +64,11 @@ #ifdef _KERNEL typedef bool udp_tun_func_t(struct mbuf *, int, struct inpcb *, const struct sockaddr *, void *); -typedef void udp_tun_icmp_t(int, struct sockaddr *, void *, void *); +typedef union { + struct icmp *icmp; + struct ip6ctlparam *ip6cp; +} udp_tun_icmp_param_t __attribute__((__transparent_union__)); +typedef void udp_tun_icmp_t(udp_tun_icmp_param_t); /* * UDP control block; one per udp. diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -147,7 +147,7 @@ struct ifnet **, struct in6_addr *); static int ni6_store_addrs(struct icmp6_nodeinfo *, struct icmp6_nodeinfo *, struct ifnet *, int); -static int icmp6_notify_error(struct mbuf **, int, int, int); +static int icmp6_notify_error(struct mbuf **, int, int); /* * Kernel module interface for updating icmp6stat. The argument is an index @@ -390,6 +390,50 @@ m_freem(m); } +int +icmp6_errmap(const struct icmp6_hdr *icmp6) +{ + + switch (icmp6->icmp6_type) { + case ICMP6_DST_UNREACH: + switch (icmp6->icmp6_code) { + case ICMP6_DST_UNREACH_NOROUTE: + case ICMP6_DST_UNREACH_ADDR: + return (EHOSTUNREACH); + case ICMP6_DST_UNREACH_NOPORT: + case ICMP6_DST_UNREACH_ADMIN: + return (ECONNREFUSED); + case ICMP6_DST_UNREACH_BEYONDSCOPE: + return (ENOPROTOOPT); + default: + return (0); /* Shouldn't happen. */ + } + case ICMP6_PACKET_TOO_BIG: + return (EMSGSIZE); + case ICMP6_TIME_EXCEEDED: + switch (icmp6->icmp6_code) { + case ICMP6_TIME_EXCEED_TRANSIT: + return (EHOSTUNREACH); + case ICMP6_TIME_EXCEED_REASSEMBLY: + return (0); + default: + return (0); /* Shouldn't happen. */ + } + case ICMP6_PARAM_PROB: + switch (icmp6->icmp6_code) { + case ICMP6_PARAMPROB_NEXTHEADER: + return (ECONNREFUSED); + case ICMP6_PARAMPROB_HEADER: + case ICMP6_PARAMPROB_OPTION: + return (ENOPROTOOPT); + default: + return (0); /* Shouldn't happen. */ + } + default: + return (0); + } +} + /* * Process a received ICMP6 message. */ @@ -467,72 +511,43 @@ case ICMP6_DST_UNREACH: icmp6_ifstat_inc(ifp, ifs6_in_dstunreach); switch (code) { - case ICMP6_DST_UNREACH_NOROUTE: - case ICMP6_DST_UNREACH_ADDR: /* PRC_HOSTDEAD is a DOS */ - code = PRC_UNREACH_NET; - break; case ICMP6_DST_UNREACH_ADMIN: icmp6_ifstat_inc(ifp, ifs6_in_adminprohib); - code = PRC_UNREACH_ADMIN_PROHIB; - break; + case ICMP6_DST_UNREACH_NOROUTE: + case ICMP6_DST_UNREACH_ADDR: case ICMP6_DST_UNREACH_BEYONDSCOPE: - /* I mean "source address was incorrect." */ - code = PRC_PARAMPROB; - break; case ICMP6_DST_UNREACH_NOPORT: - code = PRC_UNREACH_PORT; - break; + goto deliver; default: goto badcode; } - goto deliver; - break; - case ICMP6_PACKET_TOO_BIG: icmp6_ifstat_inc(ifp, ifs6_in_pkttoobig); - - /* validation is made in icmp6_mtudisc_update */ - - code = PRC_MSGSIZE; - /* + * Validation is made in icmp6_mtudisc_update. * Updating the path MTU will be done after examining * intermediate extension headers. */ goto deliver; - break; - case ICMP6_TIME_EXCEEDED: icmp6_ifstat_inc(ifp, ifs6_in_timeexceed); switch (code) { case ICMP6_TIME_EXCEED_TRANSIT: - code = PRC_TIMXCEED_INTRANS; - break; case ICMP6_TIME_EXCEED_REASSEMBLY: - code = PRC_TIMXCEED_REASS; - break; + goto deliver; default: goto badcode; } - goto deliver; - break; - case ICMP6_PARAM_PROB: icmp6_ifstat_inc(ifp, ifs6_in_paramprob); switch (code) { case ICMP6_PARAMPROB_NEXTHEADER: - code = PRC_UNREACH_PROTOCOL; - break; case ICMP6_PARAMPROB_HEADER: case ICMP6_PARAMPROB_OPTION: - code = PRC_PARAMPROB; - break; + goto deliver; default: goto badcode; } - goto deliver; - break; - case ICMP6_ECHO_REQUEST: icmp6_ifstat_inc(ifp, ifs6_in_echo); if (code != 0) @@ -856,14 +871,13 @@ ifp ? ifp->if_index : 0)); if (icmp6->icmp6_type < ICMP6_ECHO_REQUEST) { /* ICMPv6 error: MUST deliver it by spec... */ - code = PRC_NCMDS; - /* deliver */ + goto deliver; } else { /* ICMPv6 informational: MUST not deliver */ break; } deliver: - if (icmp6_notify_error(&m, off, icmp6len, code) != 0) { + if (icmp6_notify_error(&m, off, icmp6len) != 0) { /* In this case, m should've been freed. */ *mp = NULL; return (IPPROTO_DONE); @@ -892,7 +906,7 @@ } static int -icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code) +icmp6_notify_error(struct mbuf **mp, int off, int icmp6len) { struct mbuf *m; struct icmp6_hdr *icmp6; @@ -1075,7 +1089,7 @@ ip6cp.ip6c_icmp6 = icmp6; ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1); ip6cp.ip6c_off = eoff; - ip6cp.ip6c_finaldst = &icmp6dst.sin6_addr; + ip6cp.ip6c_finaldst = &icmp6dst; ip6cp.ip6c_src = &icmp6src; ip6cp.ip6c_nxt = nxt; @@ -1086,7 +1100,7 @@ } if (ip6_ctlprotox[nxt] != NULL) - ip6_ctlprotox[nxt](code, &icmp6dst, &ip6cp); + ip6_ctlprotox[nxt](&ip6cp); } *mp = m; return (0); @@ -1100,7 +1114,7 @@ void icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated) { - struct in6_addr *dst = ip6cp->ip6c_finaldst; + struct in6_addr *dst = &ip6cp->ip6c_finaldst->sin6_addr; struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6; struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */ u_int mtu = ntohl(icmp6->icmp6_mtu); diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -680,10 +680,11 @@ return ((inp->inp_vflag & INP_IPV6) != 0); } + void in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr_in6 *sa6_dst, u_int fport_arg, const struct sockaddr_in6 *src, u_int lport_arg, - int cmd, void *cmdarg, + int errno, void *cmdarg, struct inpcb *(*notify)(struct inpcb *, int)) { struct inpcb_iterator inpi = INP_ITERATOR(pcbinfo, INPLOOKUP_WLOCKPCB, @@ -692,10 +693,6 @@ struct sockaddr_in6 sa6_src; u_short fport = fport_arg, lport = lport_arg; u_int32_t flowinfo; - int errno; - - if ((unsigned)cmd >= PRC_NCMDS) - return; if (IN6_IS_ADDR_UNSPECIFIED(&sa6_dst->sin6_addr)) return; @@ -706,23 +703,6 @@ sa6_src = (src == NULL) ? sa6_any : *src; flowinfo = sa6_src.sin6_flowinfo; - /* - * Redirects go to all references to the destination, - * and use in6_rtchange to invalidate the route cache. - * Dead host indications: also use in6_rtchange to invalidate - * the cache, and deliver the error to all the sockets. - * Otherwise, if we have knowledge of the local port and address, - * deliver only to that socket. - */ - if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) { - fport = 0; - lport = 0; - bzero((caddr_t)&sa6_src.sin6_addr, sizeof(sa6_src.sin6_addr)); - - if (cmd != PRC_HOSTDEAD) - notify = in6_rtchange; - } - errno = inet6ctlerrmap[cmd]; while ((inp = inp_next(&inpi)) != NULL) { INP_WLOCK_ASSERT(inp); /* @@ -731,7 +711,7 @@ * know the value, notify. * XXX: should we avoid to notify the value to TCP sockets? */ - if (cmd == PRC_MSGSIZE && cmdarg != NULL) + if (errno == EMSGSIZE && cmdarg != NULL) ip6_notify_pmtu(inp, sa6_dst, *(uint32_t *)cmdarg); /* diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -553,7 +553,6 @@ offsetof(struct in6_ifstat, tag) / sizeof(uint64_t)], 1);\ } while (/*CONSTCOND*/ 0) -extern u_char inet6ctlerrmap[]; VNET_DECLARE(unsigned long, in6_maxmtu); #define V_in6_maxmtu VNET(in6_maxmtu) #endif /* _KERNEL */ diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -1707,23 +1707,3 @@ proto = *nxtp; } } - -/* - * System control for IP6 - * (x) - issued by icmp6_input() - */ -u_char inet6ctlerrmap[PRC_NCMDS] = { - [PRC_MSGSIZE] = EMSGSIZE, /* (x) */ - [PRC_HOSTDEAD] = EHOSTDOWN, - [PRC_HOSTUNREACH] = EHOSTUNREACH, - [PRC_UNREACH_NET] = EHOSTUNREACH, /* (x) */ - [PRC_UNREACH_HOST] = EHOSTUNREACH, - [PRC_UNREACH_PROTOCOL] = ECONNREFUSED, /* (x) */ - [PRC_UNREACH_PORT] = ECONNREFUSED, /* (x) */ - [12] = EMSGSIZE, - [PRC_UNREACH_SRCFAIL] = EHOSTUNREACH, - [PRC_TIMXCEED_INTRANS] = EHOSTUNREACH, /* (x) */ - [PRC_TIMXCEED_REASS] = 0, /* (x) */ - [PRC_PARAMPROB] = ENOPROTOOPT, /* (x) */ - [PRC_UNREACH_ADMIN_PROHIB] = ECONNREFUSED, /* (x) */ -}; diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -421,9 +421,9 @@ * | ip6c_icmp6 * ip6c_m * - * ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original - * (internal) packet carries a routing header, it may point the final - * destination address in the routing header. + * ip6c_finaldst's sin6_addr usually points to ip6c_ip6->ip6_dst. If the + * original * (internal) packet carries a routing header, it may point the + * final * destination address in the routing header. * * ip6c_src: ip6c_ip6->ip6_src + scope info + flowlabel in ip6c_ip6 * (beware of flowlabel, if you try to compare it against others) @@ -436,14 +436,13 @@ int ip6c_off; /* offset of the target proto header */ struct sockaddr_in6 *ip6c_src; /* srcaddr w/ additional info */ struct sockaddr_in6 *ip6c_dst; /* (final) dstaddr w/ additional info */ - struct in6_addr *ip6c_finaldst; /* final destination address */ + struct sockaddr_in6 *ip6c_finaldst; /* final destination address */ void *ip6c_cmdarg; /* control command dependent data */ u_int8_t ip6c_nxt; /* final next header field */ }; typedef int ip6proto_input_t(struct mbuf **, int *, int); -typedef void ip6proto_ctlinput_t(int, struct sockaddr_in6 *, - struct ip6ctlparam *); +typedef void ip6proto_ctlinput_t(struct ip6ctlparam *); int ip6proto_register(uint8_t, ip6proto_input_t, ip6proto_ctlinput_t); int ip6proto_unregister(uint8_t); #define IP6PROTO_REGISTER(prot, input, ctl) do { \ diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -323,33 +323,14 @@ } void -rip6_ctlinput(int cmd, struct sockaddr_in6 *sin6, struct ip6ctlparam *ip6cp) +rip6_ctlinput(struct ip6ctlparam *ip6cp) { - const struct sockaddr_in6 *sa6_src; - void *cmdarg; - struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange; - - if ((unsigned)cmd >= PRC_NCMDS) - return; - if (PRC_IS_REDIRECT(cmd)) - notify = in6_rtchange, ip6cp = NULL; - else if (cmd == PRC_HOSTDEAD) - ip6cp = NULL; - else if (inet6ctlerrmap[cmd] == 0) - return; + int errno; - /* - * If the parameter is from icmp6, decode it. - */ - if (ip6cp != NULL) { - cmdarg = ip6cp->ip6c_cmdarg; - sa6_src = ip6cp->ip6c_src; - } else { - cmdarg = NULL; - sa6_src = &sa6_any; - } - - in6_pcbnotify(&V_ripcbinfo, sin6, 0, sa6_src, 0, cmd, cmdarg, notify); + if ((errno = icmp6_errmap(ip6cp->ip6c_icmp6)) != 0) + in6_pcbnotify(&V_ripcbinfo, ip6cp->ip6c_finaldst, 0, + ip6cp->ip6c_src, 0, errno, ip6cp->ip6c_cmdarg, + in6_rtchange); } /* 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 @@ -248,7 +248,7 @@ } void -sctp6_ctlinput(int cmd, struct sockaddr_in6 *pktdst, struct ip6ctlparam *ip6cp) +sctp6_ctlinput(struct ip6ctlparam *ip6cp) { struct sctp_inpcb *inp; struct sctp_tcb *stcb; @@ -256,13 +256,9 @@ struct sctphdr sh; struct sockaddr_in6 src, dst; - if (inet6ctlerrmap[cmd] == 0) + if (icmp6_errmap(ip6cp->ip6c_icmp6) == 0) return; - if (ip6cp->ip6c_m == NULL) { - return; - } - /* * Check if we can safely examine the ports and the * verification tag of the SCTP common header. 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 @@ -547,28 +547,24 @@ } static void -udp6_common_ctlinput(int cmd, struct sockaddr_in6 *sin6, - struct ip6ctlparam *ip6cp, struct inpcbinfo *pcbinfo) +udp6_common_ctlinput(struct ip6ctlparam *ip6cp, struct inpcbinfo *pcbinfo) { struct udphdr uh; struct ip6_hdr *ip6; struct mbuf *m; struct inpcb *inp; - int off = 0; - void *cmdarg; - struct inpcb *(*notify)(struct inpcb *, int) = udp_notify; + int errno, off = 0; struct udp_portonly { u_int16_t uh_sport; u_int16_t uh_dport; } *uhp; - if (inet6ctlerrmap[cmd] == 0) + if ((errno = icmp6_errmap(ip6cp->ip6c_icmp6)) == 0) return; 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)) @@ -589,25 +585,25 @@ func = up->u_icmp_func; INP_RUNLOCK(inp); if (func != NULL) - func(cmd, (struct sockaddr *)ip6cp->ip6c_src, ip6cp, - up->u_tun_ctx); + func(ip6cp); } - in6_pcbnotify(pcbinfo, sin6, uh.uh_dport, ip6cp->ip6c_src, - uh.uh_sport, cmd, cmdarg, notify); + in6_pcbnotify(pcbinfo, ip6cp->ip6c_finaldst, uh.uh_dport, + ip6cp->ip6c_src, uh.uh_sport, errno, ip6cp->ip6c_cmdarg, + udp_notify); } static void -udp6_ctlinput(int cmd, struct sockaddr_in6 *sin6, struct ip6ctlparam *ctl) +udp6_ctlinput(struct ip6ctlparam *ctl) { - return (udp6_common_ctlinput(cmd, sin6, ctl, &V_udbinfo)); + return (udp6_common_ctlinput(ctl, &V_udbinfo)); } static void -udplite6_ctlinput(int cmd, struct sockaddr_in6 *sin6, struct ip6ctlparam *ctl) +udplite6_ctlinput(struct ip6ctlparam *ctl) { - return (udp6_common_ctlinput(cmd, sin6, ctl, &V_ulitecbinfo)); + return (udp6_common_ctlinput(ctl, &V_ulitecbinfo)); } static int diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c --- a/sys/netipsec/ipsec_input.c +++ b/sys/netipsec/ipsec_input.c @@ -279,23 +279,21 @@ } int -ipsec4_ctlinput(int code, struct sockaddr *sa, void *v) +ipsec4_ctlinput(ipsec_ctlinput_param_t param) { + struct icmp *icp = param.icmp; + struct ip *ip = &icp->icmp_ip; + struct sockaddr_in icmpsrc = { + .sin_len = sizeof(struct sockaddr_in), + .sin_family = AF_INET, + .sin_addr = ip->ip_dst, + }; struct in_conninfo inc; struct secasvar *sav; - struct icmp *icp; - struct ip *ip = v; uint32_t pmtu, spi; uint32_t max_pmtu; uint8_t proto; - if (code != PRC_MSGSIZE || ip == NULL) - return (EINVAL); - if (sa->sa_family != AF_INET || - sa->sa_len != sizeof(struct sockaddr_in)) - return (EAFNOSUPPORT); - - icp = __containerof(ip, struct icmp, icmp_ip); pmtu = ntohs(icp->icmp_nextmtu); if (pmtu < V_ip4_ipsec_min_pmtu) @@ -307,14 +305,14 @@ return (EINVAL); memcpy(&spi, (caddr_t)ip + (ip->ip_hl << 2), sizeof(spi)); - sav = key_allocsa((union sockaddr_union *)sa, proto, spi); + sav = key_allocsa((union sockaddr_union *)&icmpsrc, proto, spi); if (sav == NULL) return (ENOENT); key_freesav(&sav); memset(&inc, 0, sizeof(inc)); - inc.inc_faddr = satosin(sa)->sin_addr; + inc.inc_faddr = ip->ip_dst; /* Update pmtu only if its smaller than the current one. */ max_pmtu = tcp_hc_getmtu(&inc); @@ -568,7 +566,7 @@ } int -ipsec6_ctlinput(int code, struct sockaddr *sa, void *v) +ipsec6_ctlinput(ipsec_ctlinput_param_t param) { return (0); } diff --git a/sys/netipsec/ipsec_support.h b/sys/netipsec/ipsec_support.h --- a/sys/netipsec/ipsec_support.h +++ b/sys/netipsec/ipsec_support.h @@ -38,6 +38,13 @@ struct sockaddr; struct ipsec_support; struct tcpmd5_support; +struct icmp; +struct ip6ctlparam; + +typedef union { + struct icmp *icmp; + struct ip6ctlparam *ip6cp; +} ipsec_ctlinput_param_t __attribute__((__transparent_union__)); size_t ipsec_hdrsiz_inpcb(struct inpcb *); int ipsec_init_pcbpolicy(struct inpcb *); @@ -53,7 +60,7 @@ int ipsec4_pcbctl(struct inpcb *, struct sockopt *); int ipsec4_output(struct mbuf *, struct inpcb *); int ipsec4_capability(struct mbuf *, u_int); -int ipsec4_ctlinput(int, struct sockaddr *, void *); +int ipsec4_ctlinput(ipsec_ctlinput_param_t); #endif /* INET */ #ifdef INET6 @@ -63,7 +70,7 @@ int ipsec6_pcbctl(struct inpcb *, struct sockopt *); int ipsec6_output(struct mbuf *, struct inpcb *); int ipsec6_capability(struct mbuf *, u_int); -int ipsec6_ctlinput(int, struct sockaddr *, void *); +int ipsec6_ctlinput(ipsec_ctlinput_param_t); #endif /* INET6 */ struct ipsec_methods { @@ -74,7 +81,7 @@ int (*pcbctl)(struct inpcb *, struct sockopt *); size_t (*hdrsize)(struct inpcb *); int (*capability)(struct mbuf *, u_int); - int (*ctlinput)(int, struct sockaddr *, void *); + int (*ctlinput)(ipsec_ctlinput_param_t); int (*udp_input)(struct mbuf *, int, int); int (*udp_pcbctl)(struct inpcb *, struct sockopt *); @@ -156,8 +163,8 @@ (*(proto ## _ipsec_support)->methods->capability)(m, __VA_ARGS__) #define IPSEC_HDRSIZE(proto, inp) \ (*(proto ## _ipsec_support)->methods->hdrsize)(inp) -#define IPSEC_CTLINPUT(proto, code, sa, v) \ - (*(proto ## _ipsec_support)->methods->ctlinput)(code, sa, v) +#define IPSEC_CTLINPUT(proto, param) \ + (*(proto ## _ipsec_support)->methods->ctlinput)(param) #define UDPENCAP_INPUT(m, ...) \ (*ipv4_ipsec_support->methods->udp_input)(m, __VA_ARGS__) diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -167,49 +167,6 @@ #define PR_CAPATTACH 0x80 /* socket can attach in cap mode */ #define PR_SOCKBUF 0x100 /* private implementation of buffers */ -/* - * The arguments to the ctlinput routine are - * (*protosw[].pr_ctlinput)(cmd, sa, arg); - * where cmd is one of the commands below, sa is a pointer to a sockaddr, - * and arg is a `void *' argument used within a protocol family. - */ -#define PRC_ROUTEDEAD 1 /* select new route if possible ??? */ -/* was PRC_QUENCH2 3 DEC congestion bit says slow down */ -/* was PRC_QUENCH 4 Deprecated by RFC 6633 */ -#define PRC_MSGSIZE 5 /* message size forced drop */ -#define PRC_HOSTDEAD 6 /* host appears to be down */ -#define PRC_HOSTUNREACH 7 /* deprecated (use PRC_UNREACH_HOST) */ -#define PRC_UNREACH_NET 8 /* no route to network */ -#define PRC_UNREACH_HOST 9 /* no route to host */ -#define PRC_UNREACH_PROTOCOL 10 /* dst says bad protocol */ -#define PRC_UNREACH_PORT 11 /* bad port # */ -/* was PRC_UNREACH_NEEDFRAG 12 (use PRC_MSGSIZE) */ -#define PRC_UNREACH_SRCFAIL 13 /* source route failed */ -#define PRC_REDIRECT_NET 14 /* net routing redirect */ -#define PRC_REDIRECT_HOST 15 /* host routing redirect */ -#define PRC_REDIRECT_TOSNET 16 /* redirect for type of service & net */ -#define PRC_REDIRECT_TOSHOST 17 /* redirect for tos & host */ -#define PRC_TIMXCEED_INTRANS 18 /* packet lifetime expired in transit */ -#define PRC_TIMXCEED_REASS 19 /* lifetime expired on reass q */ -#define PRC_PARAMPROB 20 /* header incorrect */ -#define PRC_UNREACH_ADMIN_PROHIB 21 /* packet administrativly prohibited */ - -#define PRC_NCMDS 22 - -#define PRC_IS_REDIRECT(cmd) \ - ((cmd) >= PRC_REDIRECT_NET && (cmd) <= PRC_REDIRECT_TOSHOST) - -#ifdef PRCREQUESTS -char *prcrequests[] = { - "IFDOWN", "ROUTEDEAD", "IFUP", "DEC-BIT-QUENCH2", - "QUENCH", "MSGSIZE", "HOSTDEAD", "#7", - "NET-UNREACH", "HOST-UNREACH", "PROTO-UNREACH", "PORT-UNREACH", - "#12", "SRCFAIL-UNREACH", "NET-REDIRECT", "HOST-REDIRECT", - "TOSNET-REDIRECT", "TOSHOST-REDIRECT", "TX-INTRANS", "TX-REASS", - "PARAMPROB", "ADMIN-UNREACH" -}; -#endif - /* * The arguments to ctloutput are: * (*protosw[].pr_ctloutput)(req, so, level, optname, optval, p);