📄 udp_usrreq.c
字号:
#ifndef lintstatic char *sccsid = "@(#)udp_usrreq.c 4.7 (ULTRIX) 3/7/91";#endif lint/************************************************************************ * * * Copyright (c) 1985 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * * * 25-Feb-91 jsd * account for all input packets, including error packets * * 05-Nov-90 Mary Walker * bzero sin_zero in udp_input (as a local it isn't zero'd) * * 24-Jul-90 jaw * fix locking problem in ip_input.... * * 17-Jul-90 jsd * remove so->ref panic since it's optimized out for single-cpu * * 7-Jul-90 lp * FDDI performance. * * 06-Jun-90 R. Bhanukitsiri * Initialize mbuf pointer to zero in udp_ctloutput(). * * 26-Jan-89 gmm * Changed declartion of inpcb pointer in udp_input() to volatile * * 2-Jan-89 U. Sinkewicz * Performance enhancements to the uniprocessor kernel. * * 2-Dec-89 jsd * Panic during so->ref check for single-cpu so we don't hang * * 12-Jun-89 R. Bhanukitsiri * Add some of RFC 1066 MIB (network management). * * 30-May-89 U. Sinkewicz * Added so->ref and SO_LOCK to fix smp problem caused * by unlocking then locking socket to accommodate the * lock hierarchy and sleeps. Changed call interface to * ip_output() - needed to support asymmetric network * drivers. * * 05-May-89 Michael G. Mc Menemy * Add XTI support. * 27-Mar-89 U. Sinkewicz * Replaced udpstatistics with a macro as per lp changes * from 3/16/89. * 3-Mar-89 U. Sinkewicz * Pmax/smp merge. * 15-Jan-88 lp * Merge of final 43BSD changes. * * Chet Juszczak - 06/24/86 * * Increase udp_recvspace to allow 8K NFS datagrams * * * * Chet Juszczak - 03/12/86 * * Increase maximum datagram size to 8K * * * * Larry Cohen - 09/16/85 * * Add 43bsd alpha tape changes for subnet routing * * * ************************************************************************//* * Copyright (c) 1982 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * udp_usrreq.c 6.14 (Berkeley) 6/8/85 */#ifndef XTI#define XTI#endif#include "../h/param.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/mbuf.h"#include "../h/protosw.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/errno.h"#include "../h/stat.h"#include "../h/smp_lock.h"#include "../net/net/if.h"#include "../net/net/route.h"#include "../net/netinet/in.h"#include "../net/netinet/in_pcb.h"#include "../net/netinet/in_systm.h"#include "../net/netinet/ip.h"#include "../net/netinet/ip_var.h"#include "../net/netinet/ip_icmp.h"#include "../net/netinet/udp.h"#include "../net/netinet/udp_var.h"/* * UDP protocol implementation. * Per RFC 768, August, 1980. */struct lock_t lk_udb; /* SMP lock for udp */struct lock_t lk_udpstat; /* SMP udpstat lock */#ifdef XTIextern int xti_debug;#define PRINTXTID(level, msg) \ /* \ * level: \ * 0x01 = generate events; \ * 0x04 = acceptchk/abort support; \ * 0x08 = peek events; \ * 0x10 = tpdu T_MORE support; \ * 0x20 = oob mark; \ * 0x80 = protocol; \ */ \ if (xti_debug & (level)) \ cprintf((msg));#else#define PRINTXTID(level, msg)#endif XTIudp_init(){ int s; lockinit(&lk_udb, &lock_udb_d); lockinit(&lk_udpstat, &lock_udpstat_d); s = splnet(); smp_lock(&lk_udb, LK_RETRY); udb.inp_next = udb.inp_prev = &udb; smp_unlock(&lk_udb); splx(s);#ifdef XTI /* set-up XTI default characteristics */ xti_udpinfo.addr = sizeof(struct sockaddr_in); xti_udpinfo.options = -2; xti_udpinfo.tsdu = 8192; /* should be a constant */ xti_udpinfo.etsdu = -2; xti_udpinfo.connect = -2; xti_udpinfo.discon = -2; xti_udpinfo.servtype = T_CLTS;#endif XTI}int udpcksum = 1;int udp_ttl = UDP_TTL;udp_input(m0, ifp) struct mbuf *m0; struct ifnet *ifp;{ register struct udpiphdr *ui; register struct mbuf *m; register struct inpcb *inp_temp; int len; int s; int mod_ui = 0; struct ip ip; struct sockaddr_in udp_in; /* SMP */ volatile struct inpcb *inp; udp_in.sin_family = AF_INET; bzero(udp_in.sin_zero, 8); /* account for all packets, even if we get an error later */ UDPSTAT(udps_total++); UDPSTAT(udps_indatagrams++); /* * Get IP and UDP header together in first mbuf. */ m = m0; if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) && (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) { UDPSTAT(udps_hdrops++); return; } ui = mtod(m, struct udpiphdr *); if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2)) ip_stripoptions((struct ip *)ui, (struct mbuf *)0); /* * Make mbuf data length reflect UDP length. * If not enough data to reflect UDP length, drop. */ len = ntohs((u_short)ui->ui_ulen); if (((struct ip *)ui)->ip_len != len) { if (len > ((struct ip *)ui)->ip_len) { UDPSTAT(udps_badlen++); goto bad; } m_adj(m, len - ((struct ip *)ui)->ip_len); /* (struct ip *)ui->ip_len = len; */ } /* * Checksum extended UDP header and data. */ if (udpcksum && ui->ui_sum) { /* * Save copy of IP header in case we want to restore it for ICMP. */ ip = *(struct ip *)ui; ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_len = ui->ui_ulen; if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) { UDPSTAT(udps_badsum++); m_freem(m); return; } mod_ui++; } /* * Locate pcb for datagram. */ s = splnet(); /* SMP */ smp_lock(&lk_udb, LK_RETRY); inp = in_pcblookup(&udb, ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport, INPLOOKUP_WILDCARD);loop1: if (inp == 0) { smp_unlock(&lk_udb); /* don't send ICMP response for broadcast packet */ if (in_broadcast(ui->ui_dst)) { UDPSTAT(udps_noports++); goto bad; } if (mod_ui) *(struct ip *)ui = ip; icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT, ifp); splx(s); UDPSTAT(udps_noports++); UDPSTAT(udps_nospace++); /* count it as a dropped packet */ return; } if (smp){ smp_lock(&inp->inp_socket->lk_socket, LK_RETRY); while (inp->inp_socket->ref >0){ smp_unlock(&inp->inp_socket->lk_socket); smp_unlock(&lk_udb); while ( (inp) && (inp->inp_socket->ref >0) ) ; smp_lock(&lk_udb, LK_RETRY); inp = in_pcblookup(&udb, ui->ui_src,ui->ui_sport, ui->ui_dst, ui->ui_dport, INPLOOKUP_WILDCARD); if (inp == 0) goto loop1; smp_lock(&inp->inp_socket->lk_socket, LK_RETRY); } inp_temp = in_pcblookup(&udb, ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport, INPLOOKUP_WILDCARD); if (inp_temp != inp){ smp_unlock(&inp->inp_socket->lk_socket); smp_unlock(&lk_udb); splx(s); UDPSTAT(udps_noports++); goto bad; } } smp_unlock(&lk_udb); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ udp_in.sin_port = ui->ui_sport; udp_in.sin_addr = ui->ui_src; m->m_len -= sizeof (struct udpiphdr); m->m_off += sizeof (struct udpiphdr); if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m, (struct mbuf *)0) == 0) { smp_unlock(&inp->inp_socket->lk_socket); splx(s); goto bad; }#ifdef XTI if (((struct socket *) inp->inp_socket)->so_xticb.xti_evtenabled) { ((struct socket *)inp->inp_socket)->so_xticb.xti_evtarray[XTI_EVT_T_DATA]++; PRINTXTID(1,("T_DATA, len =%d,but 1 event generated\n",len - sizeof(struct udphdr))) }#endif XTI sorwakeup(inp->inp_socket); smp_unlock(&inp->inp_socket->lk_socket); splx(s); return;bad: UDPSTAT(udps_nospace++); /* really number of "dropped" packets */ m_freem(m);}/* * Notify a udp user of an asynchronous error; * just wake up so that he can collect error status. */udp_notify(inp) register struct inpcb *inp;{ /* Ensure that socket is locked because * routines that so*wakeup call write to the socket. */ /* Note that here, lk_udb is already held so if we use * SO_LOCK, then SO_LOCK could so->ref busy, and we could * starve because lk_udb is held for the entire operation. */ smp_lock(&inp->inp_socket->lk_socket, LK_RETRY); sorwakeup(inp->inp_socket); sowwakeup(inp->inp_socket); smp_unlock(&inp->inp_socket->lk_socket);}udp_ctlinput(cmd, sa) int cmd; struct sockaddr *sa;{ extern u_char inetctlerrmap[]; struct sockaddr_in *sin; int in_rtchange(); if ((unsigned) cmd > PRC_NCMDS) return; if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) return; sin = (struct sockaddr_in *)sa; if (sin->sin_addr.s_addr == INADDR_ANY) return; switch (cmd) { case PRC_QUENCH: break; case PRC_ROUTEDEAD: case PRC_REDIRECT_NET: case PRC_REDIRECT_HOST: case PRC_REDIRECT_TOSNET: case PRC_REDIRECT_TOSHOST: smp_lock(&lk_udb, LK_RETRY); in_pcbnotify(&udb, &sin->sin_addr, 0, in_rtchange); smp_unlock(&lk_udb); break; default: if (inetctlerrmap[cmd] == 0) return; /* XXX */notify: smp_lock(&lk_udb, LK_RETRY); in_pcbnotify(&udb, &sin->sin_addr, (int)inetctlerrmap[cmd], udp_notify); smp_unlock(&lk_udb); }}udp_output(inp, m0) register struct inpcb *inp; struct mbuf *m0;{ register struct mbuf *m; register struct udpiphdr *ui; register int len = 0; int s; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -