📄 udp_usrreq.c
字号:
{ /* * No matching pcb found; discard datagram. * (No need to send an ICMP Port Unreachable * for a broadcast or multicast datgram.) */#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, ip->ip_dst.s_addr, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif udpstat.udps_noportbcast++; goto bad; }#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, last->so_fd, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in, m, (struct mbuf *)0) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV, last->so_fd)#endif /* INCLUDE_WVNET */#endif udpstat.udps_fullsock++; goto bad; } sorwakeup(last); return; } } if (in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) { 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.5BSD 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.lh_first; inp != NULL; inp = inp->inp_list.le_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) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, last->so_fd, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in, n, (struct mbuf *)0) == 0) { m_freem(n);#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV, last->so_fd)#endif /* INCLUDE_WVNET */#endif udpstat.udps_fullsock++; } else sorwakeup(last); } } last = inp->inp_socket; /* * Don't look for additional matches if this one does * not have either the SO_REUSEPORT or SO_REUSEADDR * socket options 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 these options after setting them. */ if ((last->so_options & (SO_REUSEPORT|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.) */#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, ip->ip_dst.s_addr, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif udpstat.udps_noportbcast++; goto bad; }#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, last->so_fd, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&udp_in, m, (struct mbuf *)0) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV, last->so_fd)#endif /* INCLUDE_WVNET */#endif udpstat.udps_fullsock++; goto bad; } sorwakeup(last); return; } /* * Locate pcb for datagram. use the cached pcb if it matches. */ inp = udp_last_inpcb; if ((inp != NULL) && (inp->inp_lport == uh->uh_dport) && (inp->inp_fport == uh->uh_sport) && (inp->inp_faddr.s_addr == ip->ip_src.s_addr) && (inp->inp_laddr.s_addr == ip->ip_dst.s_addr)) { goto pcbMatchFound; } else {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_VERBOSE event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_VERBOSE, 44, 17, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_CACHEMISS, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, ip->ip_dst.s_addr, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif udpstat.udpps_pcbcachemiss++; /* * Locate pcb for datagram. */ inp = in_pcblookuphash(&udbinfo, ip->ip_src, uh->uh_sport, ip->ip_dst, uh->uh_dport, 1); if (inp == NULL) { /* look up for the wildcard match, hash look up failed */ udpstat.udpps_pcbhashmiss++; udpstat.udps_noport++;#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 18, 8, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_SEARCHFAIL, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, ip->ip_dst.s_addr, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif if (m->m_flags & (M_BCAST | M_MCAST)) { udpstat.udps_noportbcast++; goto bad; }#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_WARNING, 19, 9, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_NOPORT, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, ip->ip_dst.s_addr, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif *ip = save_ip; /* bug fix mentioned in Stevens VolII page774,(vinai) */ /* ip->ip_len += iphlen; */ if (_icmpErrorHook != NULL) (*_icmpErrorHook) (m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0); return; } } udp_last_inpcb = inp; pcbMatchFound:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_PORTIN_EVENT_4 (NET_CORE_EVENT, WV_NET_INFO, 56, 18, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_PCBGOOD, WV_NET_RECV, ip->ip_src.s_addr, uh->uh_sport, inp->inp_socket->so_fd, uh->uh_dport)#endif /* INCLUDE_WVNET */#endif /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ udp_in.sin_port = uh->uh_sport; udp_in.sin_addr = ip->ip_src; if (inp->inp_flags & INP_CONTROLOPTS) { struct mbuf **mp = &opts; if (inp->inp_flags & INP_RECVDSTADDR) { *mp = udp_saveopt((caddr_t) &ip->ip_dst, sizeof(struct in_addr), IP_RECVDSTADDR); if (*mp) mp = &(*mp)->m_next; }#ifdef notyet /* options were tossed above */ if (inp->inp_flags & INP_RECVOPTS) { *mp = udp_saveopt((caddr_t) opts_deleted_above, sizeof(struct in_addr), IP_RECVOPTS); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ if (inp->inp_flags & INP_RECVRETOPTS) { *mp = udp_saveopt((caddr_t) ip_srcroute(), sizeof(struct in_addr), IP_RECVRETOPTS); if (*mp) mp = &(*mp)->m_next; }#endif } iphlen += sizeof(struct udphdr); m->m_len -= iphlen; m->m_pkthdr.len -= iphlen; m->m_data += iphlen; if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m, opts) == 0) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_WARNING event */ WV_NET_PORTIN_EVENT_1 (NET_CORE_EVENT, WV_NET_WARNING, 17, 7, uh->uh_sport, uh->uh_dport, WV_NETEVENT_UDPIN_FULLSOCK, WV_NET_RECV, inp->inp_socket->so_fd)#endif /* INCLUDE_WVNET */#endif udpstat.udps_fullsock++; goto bad; } sorwakeup(inp->inp_socket); return;bad: m_freem(m); if (opts) m_freem(opts);}/* * Create a "control" mbuf containing the specified data * with the specified type for presentation with a datagram. */struct mbuf *udp_saveopt(p, size, type) caddr_t p; register int size; int type;{ register struct cmsghdr *cp; struct mbuf *m; if ((m = mBufClGet(M_DONTWAIT, MT_CONTROL, CL_SIZE_128, TRUE)) == NULL) return ((struct mbuf *) NULL); cp = (struct cmsghdr *) mtod(m, struct cmsghdr *); bcopy(p, CMSG_DATA(cp), size); size += sizeof(*cp); m->m_len = size; cp->cmsg_len = size; cp->cmsg_level = IPPROTO_IP; cp->cmsg_type = type; return (m);}/* * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */static voidudp_notify(inp, error) register struct inpcb *inp; int error;{#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_INFO, 48, 12, WV_NETEVENT_UDPNOTIFY_START, inp->inp_socket->so_fd, error)#endif /* INCLUDE_WVNET */#endif inp->inp_socket->so_error = error; sorwakeup(inp->inp_socket);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -