Index: net/if_vxlan.c =================================================================== --- net/if_vxlan.c +++ net/if_vxlan.c @@ -928,9 +928,8 @@ if_printf(ifp, "cannot create socket: %d\n", error); return (error); } - error = udp_set_kernel_tunneling(vso->vxlso_sock, - vxlan_rcv_udp_packet, vso); + vxlan_rcv_udp_packet, NULL, vso); if (error) { if_printf(ifp, "cannot set tunneling function: %d\n", error); return (error); Index: netinet/sctputil.c =================================================================== --- netinet/sctputil.c +++ netinet/sctputil.c @@ -7088,7 +7088,7 @@ } /* Call the special UDP hook. */ if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket), - sctp_recv_udp_tunneled_packet, NULL))) { + sctp_recv_udp_tunneled_packet, NULL, NULL))) { sctp_over_udp_stop(); return (ret); } @@ -7112,7 +7112,7 @@ } /* Call the special UDP hook. */ if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket), - sctp_recv_udp_tunneled_packet, NULL))) { + sctp_recv_udp_tunneled_packet, NULL, NULL))) { sctp_over_udp_stop(); return (ret); } Index: netinet/udp_usrreq.c =================================================================== --- netinet/udp_usrreq.c +++ netinet/udp_usrreq.c @@ -787,11 +787,20 @@ inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport, ip->ip_src, uh->uh_sport, INPLOOKUP_RLOCKPCB, NULL); if (inp != NULL) { + struct udpcb *up; + + up = intoudpcb(inp); INP_RLOCK_ASSERT(inp); - if (inp->inp_socket != NULL) { - udp_notify(inp, inetctlerrmap[cmd]); + if (up->u_icmp_func != NULL) { + INP_RUNLOCK(inp); + (*up->u_icmp_func)(cmd, sa, + vip, up->u_tun_ctx); + } else { + if (inp->inp_socket != NULL) { + udp_notify(inp, inetctlerrmap[cmd]); + } + INP_RUNLOCK(inp); } - INP_RUNLOCK(inp); } } else in_pcbnotifyall(pcbinfo, faddr, inetctlerrmap[cmd], @@ -1748,7 +1757,7 @@ #endif /* INET */ int -udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, void *ctx) +udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, udp_tun_icmp_t i, void *ctx) { struct inpcb *inp; struct udpcb *up; @@ -1759,11 +1768,13 @@ KASSERT(inp != NULL, ("udp_set_kernel_tunneling: inp == NULL")); INP_WLOCK(inp); up = intoudpcb(inp); - if (up->u_tun_func != NULL) { + if ((up->u_tun_func != NULL) || + (up->u_icmp_func != NULL)) { INP_WUNLOCK(inp); return (EBUSY); } up->u_tun_func = f; + up->u_icmp_func = i; up->u_tun_ctx = ctx; INP_WUNLOCK(inp); return (0); Index: netinet/udp_var.h =================================================================== --- netinet/udp_var.h +++ netinet/udp_var.h @@ -57,12 +57,14 @@ typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *, const struct sockaddr *, void *); - +typedef void(*udp_tun_icmp_t)(int cmd, struct sockaddr *sa, void *vip, void *); + /* * UDP control block; one per udp. */ struct udpcb { udp_tun_func_t u_tun_func; /* UDP kernel tunneling callback. */ + udp_tun_icmp_t u_icmp_func; /* UDP kernel tunneling icmp callback */ u_int u_flags; /* Generic UDP flags. */ uint16_t u_rxcslen; /* Coverage for incoming datagrams. */ uint16_t u_txcslen; /* Coverage for outgoing datagrams. */ @@ -179,7 +181,7 @@ int udp_shutdown(struct socket *so); int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f, - void *ctx); + udp_tun_icmp_t i, void *ctx); #endif /* _KERNEL */