⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_output.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)ip_output.c	4.5	(ULTRIX)	11/9/90";#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				* * *	02-Aug-90	lp *		Fix ROUTETOIF case in route cache extensions. * *	31-Jul-90	jsd *		word align optlen for mips when inserting IP options * *	7-Jul-90	lp *		FDDI performance. * *	2-Jan-90	U. Sinkewicz *		Performance enhancements to uniprocessor kernel. * *	11-14-89	Ursula Sinkewicz *		Removed lk_ifnet and lk_in_ifaddr to coincide with *		slip changes. * *	10-18-89   	Uttam Shikarpur					* *		Added counters for network management to keep track	* *		of: 1) Number of IP packets sent out (ips_totalsent)	* *		    2) Number of error-free IP packets discarded	* *		       (ips_outdiscard)					* *		    3) Number of packets that were fragmented 	  	* *		       (ips_outpktsfrag)				* *		    4) Number of fragments that were created		* *		       (ips_outtotalfrag)				* *		    5) Number of packets that could not be fragmented 	* *		       (ips_outfragsfail)				* *									* *	30-May-89	U. Sinkewicz *		Added support for nonsymmetric network drivers. * *	11-Apr-89	Ursula Sinkewicz *		Picked up memenemy changes from 2/10/89 making ip options *		long word aligned before insertion in output packets. * *	27-Mar-89	Ursula Sinkewicz *		Lowered ipl on lk_rtentry, lk_ifnet, lk_in_ifaddr as per *		lp changes on 3/16/89. * *	3 Mar 89	Ursula Sinkewicz *		Added support for new directory layout to smp file. * * 	13 Feb 89	Ursula Sinkewicz *		SMP: Added lk_in_ifaddr, lk_ifnet. * *	15-Jan-88	lp *		Merge of final 43BSD changes. * *	Larry Cohen - 01/28/87 *		Add ip ouput control routine and ip options processing *			routine *									* *	Chet Juszczak - 03/12/86					* *		Add new packet fragmentation code for NFS		* *									* *	Larry Cohen  -	09/16/85					* * 		Add 43bsd alpha tape changes for subnet routing		* *									* ************************************************************************//* * Copyright (c) 1982, 1986 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * *	ip_output.c	7.6 (Berkeley) 6/20/87 */#include "../h/param.h"#include "../h/cpudata.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/proc.h"#include "../h/mbuf.h"#include "../h/errno.h"#include "../h/protosw.h"#include "../h/socket.h"#include "../h/socketvar.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_systm.h"#include "../net/netinet/in_var.h"#include "../net/netinet/in_pcb.h"#include "../net/netinet/ip.h"#include "../net/netinet/ip_var.h"#ifdef vax#include "../machine/mtpr.h"#endifstruct mbuf *ip_insertoptions();/* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed./*  * SMP: enter from tcp_output and protosw with NO locks set. * Results in a hack in tcp_output but you cannot require * locks be set coming in because of possibility of being triggered from * protosw.  Further, there is no data manipulated here that is under the * control of the socket lock. */ip_output(m, opt, ro, flags, so)	struct mbuf *m;	struct mbuf *opt;	struct route *ro;	int flags;	struct socket *so;{	register struct ip *ip;	register struct ifnet *ifp;	int len, hlen = sizeof (struct ip), off, error = 0;	struct route iproute;	struct sockaddr_in *dst;	int saveaffinity;	if (opt)						m = ip_insertoptions(m, opt, &hlen);	ip = mtod(m, struct ip *);	/*	 * Fill in IP header.	 */	if ((flags & IP_FORWARDING) == 0) {		ip->ip_v = IPVERSION;		ip->ip_off &= IP_DF;		ip->ip_id = htons(ip_id++);/* * CJ - SUN has the following line before this if statement. */		ip->ip_hl = hlen >> 2;	} else		hlen = ip->ip_hl << 2;	/*	 * Route packet.	 */	RTLOCK();	if (ro == 0) {		ro = &iproute;		bzero((caddr_t)ro, sizeof (*ro));	}	dst = (struct sockaddr_in *)&ro->ro_dst;	/*	 * If there is a cached route,	 * check that it is to the same destination	 * and is still up.  If not, free it and try again.	 */	if (ro->ro_rt && (ro->ro_rt->rt_flags & RTF_UP) &&	   dst->sin_addr.s_addr == ip->ip_dst.s_addr) {		if((ifp = ro->ro_rt->rt_ifp) && (flags&IP_ROUTETOIF)) {			RTUNLOCK();			goto fastout;		}	} else {		if(ro->ro_rt) {			rtfree(ro->ro_rt);			ro->ro_rt = (struct rtentry *)0;		}	}	if (ro->ro_rt == 0) {		dst->sin_family = AF_INET;		dst->sin_addr = ip->ip_dst;	}	/*	 * If routing to interface only,	 * short circuit routing lookup.	 */	if (flags & IP_ROUTETOIF) {		struct in_ifaddr *ia;		ia = (struct in_ifaddr *)ifa_ifwithdstaddr(dst);		if (ia == 0)			ia = in_iaonnetof(in_netof(ip->ip_dst));		if (ia == 0) {			error = ENETUNREACH;			RTUNLOCK();			IPSTAT(ips_outdiscard++); /* a packet was discarded*/			goto bad;		}		ifp = ia->ia_ifp;	} else {		if (ro->ro_rt == 0)			rtalloc(ro);		if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {			if (in_localaddr(ip->ip_dst))				error = EHOSTUNREACH;			else				error = ENETUNREACH;			RTUNLOCK();			IPSTAT(ips_outdiscard++); /* a packet was discarded */			goto bad;		}		ro->ro_rt->rt_use++;		if (ro->ro_rt->rt_flags & RTF_GATEWAY)			dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;	}	RTUNLOCK();	/*	 * Look for broadcast address and	 * and verify user is allowed to send	 * such a packet.	 */	if (in_broadcast(dst->sin_addr)) {		if ((ifp->if_flags & IFF_BROADCAST) == 0) {			error = EADDRNOTAVAIL;			IPSTAT(ips_outdiscard++); /* a packet was discarded */			goto bad;		}		if ((flags & IP_ALLOWBROADCAST) == 0) {			error = EACCES;			goto bad;		}		/* don't allow broadcast messages to be fragmented */		if (ip->ip_len > ifp->if_mtu) {			error = EMSGSIZE;			IPSTAT(ips_outfragsfail++); /* a packet could						     * not be fragmented						     */			goto bad;		}	}fastout:	/*	 * If source address not specified yet, use address	 * of outgoing interface.	 */	if (ip->ip_src.s_addr == INADDR_ANY) {		register struct in_ifaddr *ia;		for (ia = in_ifaddr; ia; ia = ia->ia_next)			if (ia->ia_ifp == ifp) {				ip->ip_src = IA_SIN(ia)->sin_addr;				break;			}	}	/*	 * If small enough for interface, can just send directly.	 */	if (ip->ip_len <= ifp->if_mtu) {		ip->ip_len = htons((u_short)ip->ip_len);		ip->ip_off = htons((u_short)ip->ip_off);		ip->ip_sum = 0;		ip->ip_sum = in_cksum(m, hlen);		/* Support for nonsymm net devices. 8.9.88.us */		if ( !smp)			error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);		else {		if ( ifp->d_affinity != boot_cpu_mask)			error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);		else{			if (so){				so->ref = 24;				smp_unlock(&so->lk_socket);			}			CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity);			error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);			RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);			if ( so  ){						smp_lock(&so->lk_socket, LK_RETRY);				so->ref = 0;			}		}		}		/* for network management */		if (!error)	/* if there was no error while sending */			IPSTAT(ips_totalsent++); /* counter for total						  * IP packets sent out.						  */		goto done;	}	/*	 * Too large for interface; fragment if possible.	 * Must be able to put at least 8 bytes per fragment.	 */	if (ip->ip_off & IP_DF) {		error = EMSGSIZE;		IPSTAT(ips_outfragsfail++); /* a packet could					     * not be fragmented					     */		goto bad;	}	len = (ifp->if_mtu - hlen) &~ 7;	if (len < 8) {		error = EMSGSIZE;		IPSTAT(ips_outfragsfail++); /* a packet could					     * not be fragmented					     */		goto bad;	}	/*	 * CJ:	 * Call to new packet fragmentation routine.	 * Added for NFS.	 */	if (hlen == sizeof (struct ip) &&	    ip_frag2(m, ip, len, &error, ifp, dst, so)) {		IPSTAT(ips_outpktsfrag++); /* packet was successfully frag.*/		goto done;	}	/*	 * Discard IP header from logical mbuf for m_copy's sake.	 * Loop through length of segment, make a copy of each	 * part and output.	 */	m->m_len -= sizeof (struct ip);	m->m_off += sizeof (struct ip);	for (off = 0; off < ip->ip_len-hlen; off += len) {		struct mbuf *mh = m_get(M_DONTWAIT, MT_DATA);		struct ip *mhip;		if (mh == 0) {			error = ENOBUFS;			IPSTAT(ips_outdiscard++); /* a packet was discarded */			goto bad;		}		mh->m_off = MMAXOFF - hlen;		mhip = mtod(mh, struct ip *);		*mhip = *ip;		if (hlen > sizeof (struct ip)) {			int olen = ip_optcopy(ip, mhip, off);			mh->m_len = sizeof (struct ip) + olen;		} else			mh->m_len = sizeof (struct ip);		mhip->ip_off = (off >> 3) + (ip->ip_off & ~IP_MF);		if (ip->ip_off & IP_MF)			mhip->ip_off |= IP_MF;		if (off + len >= ip->ip_len-hlen)			len = mhip->ip_len = ip->ip_len - hlen - off;		else {			mhip->ip_len = len;			mhip->ip_off |= IP_MF;		}		mhip->ip_len += sizeof (struct ip);		mhip->ip_len = htons((u_short)mhip->ip_len);		mh->m_next = m_copy(m, off, len);		if (mh->m_next == 0) {			(void) m_free(mh);			error = ENOBUFS;	/* ??? */			IPSTAT(ips_outdiscard++); /* a packet was discarded */			goto bad;		}		mhip->ip_off = htons((u_short)mhip->ip_off);		mhip->ip_sum = 0;		mhip->ip_sum = in_cksum(mh, hlen);		/* Support for nonsymm net devices. 8.9.88.us */		if (!smp)			error = (*ifp->if_output)(ifp, mh, (struct sockaddr *)dst);		else{		if (ifp->d_affinity != boot_cpu_mask)			error = (*ifp->if_output)(ifp, mh, (struct sockaddr *)dst);		else{			if (so){					so->ref = 25;				smp_unlock(&so->lk_socket);			}			CALL_TO_NONSMP_DRIVER( (*ifp),saveaffinity);			error = (*ifp->if_output)(ifp, mh, (struct sockaddr *)dst);			RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -