| version 1.3.4.1, 1993/09/24 08:55:04 |
version 1.4, 1993/12/06 04:59:45 |
|
|
| #include "socketvar.h" |
#include "socketvar.h" |
| #include "stat.h" |
#include "stat.h" |
| |
|
| #include "machine/cpu.h" |
|
| |
|
| #include "../net/if.h" |
#include "../net/if.h" |
| #include "../net/route.h" |
#include "../net/route.h" |
| |
|
| Line 147 udp_input(m, iphlen) |
|
| Line 145 udp_input(m, iphlen) |
|
| return; |
return; |
| } |
} |
| } |
} |
| |
#ifdef MULTICAST |
| |
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) || |
| |
in_broadcast(ip->ip_dst)) { |
| |
struct socket *last; |
| |
/* |
| |
* Deliver a multicast or broadcast datagram to *all* sockets |
| |
* for which the local and remote addresses and ports match |
| |
* those of the incoming datagram. This allows more than |
| |
* one process to receive multi/broadcasts on the same port. |
| |
* (This really ought to be done for unicast datagrams as |
| |
* well, but that would cause problems with existing |
| |
* applications that open both address-specific sockets and |
| |
* a wildcard socket listening to the same port -- they would |
| |
* end up receiving duplicates of every unicast datagram. |
| |
* Those applications open the multiple sockets to overcome an |
| |
* inadequacy of the UDP socket interface, but for backwards |
| |
* compatibility we avoid the problem here rather than |
| |
* fixing the interface. Maybe 4.4BSD will remedy this?) |
| |
*/ |
| |
|
| |
/* |
| |
* Construct sockaddr format source address. |
| |
*/ |
| |
udp_in.sin_port = uh->uh_sport; |
| |
udp_in.sin_addr = ip->ip_src; |
| |
m->m_len -= sizeof (struct udpiphdr); |
| |
m->m_data += sizeof (struct udpiphdr); |
| |
/* |
| |
* Locate pcb(s) for datagram. |
| |
* (Algorithm copied from raw_intr().) |
| |
*/ |
| |
last = NULL; |
| |
for (inp = udb.inp_next; inp != &udb; inp = inp->inp_next) { |
| |
if (inp->inp_lport != uh->uh_dport) |
| |
continue; |
| |
if (inp->inp_laddr.s_addr != INADDR_ANY) { |
| |
if (inp->inp_laddr.s_addr != |
| |
ip->ip_dst.s_addr) |
| |
continue; |
| |
} |
| |
if (inp->inp_faddr.s_addr != INADDR_ANY) { |
| |
if (inp->inp_faddr.s_addr != |
| |
ip->ip_src.s_addr || |
| |
inp->inp_fport != uh->uh_sport) |
| |
continue; |
| |
} |
| |
|
| |
if (last != NULL) { |
| |
struct mbuf *n; |
| |
|
| |
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { |
| |
if (sbappendaddr(&last->so_rcv, |
| |
(struct sockaddr *)&udp_in, |
| |
n, (struct mbuf *)0) == 0) |
| |
m_freem(n); |
| |
else |
| |
sorwakeup(last); |
| |
} |
| |
} |
| |
last = inp->inp_socket; |
| |
/* |
| |
* Don't look for additional matches if this one |
| |
* does not have the SO_REUSEADDR socket option set. |
| |
* This heuristic avoids searching through all pcbs |
| |
* in the common case of a non-shared port. It |
| |
* assumes that an application will never clear |
| |
* the SO_REUSEADDR option after setting it. |
| |
*/ |
| |
if ((last->so_options & SO_REUSEADDR) == 0) |
| |
break; |
| |
} |
| |
|
| |
if (last == NULL) { |
| |
/* |
| |
* No matching pcb found; discard datagram. |
| |
* (No need to send an ICMP Port Unreachable |
| |
* for a broadcast or multicast datgram.) |
| |
*/ |
| |
goto bad; |
| |
} |
| |
if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in, |
| |
m, (struct mbuf *)0) == 0) |
| |
goto bad; |
| |
sorwakeup(last); |
| |
return; |
| |
} |
| |
#endif |
| /* |
/* |
| * Locate pcb for datagram. |
* Locate pcb for datagram. |
| */ |
*/ |
| Line 165 udp_input(m, iphlen) |
|
| Line 249 udp_input(m, iphlen) |
|
| if (inp == 0) { |
if (inp == 0) { |
| /* don't send ICMP response for broadcast packet */ |
/* don't send ICMP response for broadcast packet */ |
| udpstat.udps_noport++; |
udpstat.udps_noport++; |
| if (m->m_flags & M_BCAST) { |
#ifndef MULTICAST |
| |
/* XXX why don't we do this with MULTICAST? */ |
| |
if (m->m_flags & (M_BCAST | M_MCAST)) { |
| udpstat.udps_noportbcast++; |
udpstat.udps_noportbcast++; |
| goto bad; |
goto bad; |
| } |
} |
| |
#endif |
| *ip = save_ip; |
*ip = save_ip; |
| ip->ip_len += iphlen; |
ip->ip_len += iphlen; |
| icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT); |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT); |
| Line 350 udp_output(inp, m, addr, control) |
|
| Line 437 udp_output(inp, m, addr, control) |
|
| ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
| udpstat.udps_opackets++; |
udpstat.udps_opackets++; |
| error = ip_output(m, inp->inp_options, &inp->inp_route, |
error = ip_output(m, inp->inp_options, &inp->inp_route, |
| inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)); |
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST) |
| |
#ifdef MULTICAST |
| |
| IP_MULTICASTOPTS, inp->inp_moptions |
| |
#endif |
| |
); |
| |
|
| if (addr) { |
if (addr) { |
| in_pcbdisconnect(inp); |
in_pcbdisconnect(inp); |