Changeset View
Changeset View
Standalone View
Standalone View
sys/netinet/udp_usrreq.c
Show First 20 Lines • Show All 734 Lines • ▼ Show 20 Lines | udp_notify(struct inpcb *inp, int errno) | ||||
inp->inp_socket->so_error = errno; | inp->inp_socket->so_error = errno; | ||||
sorwakeup(inp->inp_socket); | sorwakeup(inp->inp_socket); | ||||
sowwakeup(inp->inp_socket); | sowwakeup(inp->inp_socket); | ||||
return (inp); | return (inp); | ||||
} | } | ||||
#ifdef INET | #ifdef INET | ||||
static void | static void | ||||
udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip, | udp_common_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip, | ||||
struct inpcbinfo *pcbinfo) | struct inpcbinfo *pcbinfo) | ||||
{ | { | ||||
struct ip *ip = vip; | |||||
struct udphdr *uh; | struct udphdr *uh; | ||||
struct in_addr faddr; | |||||
struct inpcb *inp; | struct inpcb *inp; | ||||
faddr = ((struct sockaddr_in *)sa)->sin_addr; | if (sin->sin_addr.s_addr == INADDR_ANY) | ||||
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY) | |||||
return; | return; | ||||
if (PRC_IS_REDIRECT(cmd)) { | if (PRC_IS_REDIRECT(cmd)) { | ||||
/* signal EHOSTDOWN, as it flushes the cached route */ | /* signal EHOSTDOWN, as it flushes the cached route */ | ||||
in_pcbnotifyall(pcbinfo, faddr, EHOSTDOWN, udp_notify); | in_pcbnotifyall(pcbinfo, sin->sin_addr, EHOSTDOWN, udp_notify); | ||||
return; | return; | ||||
} | } | ||||
/* | /* | ||||
* Hostdead is ugly because it goes linearly through all PCBs. | * Hostdead is ugly because it goes linearly through all PCBs. | ||||
* | * | ||||
* XXX: We never get this from ICMP, otherwise it makes an excellent | * XXX: We never get this from ICMP, otherwise it makes an excellent | ||||
* DoS attack on machines with many connections. | * DoS attack on machines with many connections. | ||||
*/ | */ | ||||
if (cmd == PRC_HOSTDEAD) | if (cmd == PRC_HOSTDEAD) | ||||
ip = NULL; | ip = NULL; | ||||
else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) | else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) | ||||
return; | return; | ||||
if (ip != NULL) { | 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, faddr, uh->uh_dport, | 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_WLOCKPCB, NULL); | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
INP_WLOCK_ASSERT(inp); | INP_WLOCK_ASSERT(inp); | ||||
if (inp->inp_socket != NULL) { | if (inp->inp_socket != NULL) { | ||||
udp_notify(inp, inetctlerrmap[cmd]); | udp_notify(inp, inetctlerrmap[cmd]); | ||||
} | } | ||||
INP_WUNLOCK(inp); | INP_WUNLOCK(inp); | ||||
} else { | } else { | ||||
inp = in_pcblookup(pcbinfo, faddr, uh->uh_dport, | inp = in_pcblookup(pcbinfo, sin->sin_addr, uh->uh_dport, | ||||
ip->ip_src, uh->uh_sport, | ip->ip_src, uh->uh_sport, | ||||
INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); | INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL); | ||||
if (inp != NULL) { | if (inp != NULL) { | ||||
struct udpcb *up; | struct udpcb *up; | ||||
void *ctx; | void *ctx; | ||||
udp_tun_icmp_t *func; | udp_tun_icmp_t *func; | ||||
up = intoudpcb(inp); | up = intoudpcb(inp); | ||||
ctx = up->u_tun_ctx; | ctx = up->u_tun_ctx; | ||||
func = up->u_icmp_func; | func = up->u_icmp_func; | ||||
INP_RUNLOCK(inp); | INP_RUNLOCK(inp); | ||||
if (func != NULL) | if (func != NULL) | ||||
(*func)(cmd, sa, vip, ctx); | (*func)(cmd, (struct sockaddr *)sin, | ||||
ip, ctx); | |||||
} | } | ||||
} | } | ||||
} else | } else | ||||
in_pcbnotifyall(pcbinfo, faddr, inetctlerrmap[cmd], | in_pcbnotifyall(pcbinfo, sin->sin_addr, inetctlerrmap[cmd], | ||||
udp_notify); | udp_notify); | ||||
} | } | ||||
static void | static void | ||||
udp_ctlinput(int cmd, struct sockaddr *sa, void *vip) | udp_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) | ||||
{ | { | ||||
return (udp_common_ctlinput(cmd, sa, vip, &V_udbinfo)); | return (udp_common_ctlinput(cmd, sin, ip, &V_udbinfo)); | ||||
} | } | ||||
static void | static void | ||||
udplite_ctlinput(int cmd, struct sockaddr *sa, void *vip) | udplite_ctlinput(int cmd, struct sockaddr_in *sin, struct ip *ip) | ||||
{ | { | ||||
return (udp_common_ctlinput(cmd, sa, vip, &V_ulitecbinfo)); | return (udp_common_ctlinput(cmd, sin, ip, &V_ulitecbinfo)); | ||||
} | } | ||||
#endif /* INET */ | #endif /* INET */ | ||||
static int | static int | ||||
udp_pcblist(SYSCTL_HANDLER_ARGS) | udp_pcblist(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_udbinfo, | struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_udbinfo, | ||||
INPLOOKUP_RLOCKPCB); | INPLOOKUP_RLOCKPCB); | ||||
▲ Show 20 Lines • Show All 972 Lines • Show Last 20 Lines |