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

📄 dli_setopt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef	lintstatic char *sccsid = "@(#)dli_setopt.c	4.2	ULTRIX	9/4/90";#endif	lint/* * Program dli_setopt.c,  Module DLI  * * Copyright (C) 1985, 1988 by * Digital Equipment Corporation, Maynard, Mass. * * 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. * * 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. * * * Networks & Communications Software Engineering * * IDENT HISTORY: * * 1.00 10-Jul-1985 *      DECnet-ULTRIX   V1.0 * * 2.01 18-Mar-1988 *      DECnet-ULTRIX   V2.4 *		- Allowed use of reserved bit in individual and group SAPs * * */#include "../../h/param.h"#include "../../h/systm.h"#include "../../h/mbuf.h"#include "../../h/socket.h"#include "../../h/socketvar.h"#include "../../h/protosw.h"#include "../../h/errno.h"#include "../../h/ioctl.h"#include "../../h/smp_lock.h"#include "../../h/cpudata.h"#include "../h/user.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/proc.h"#include "../../net/net/if.h"#include "../../net/netinet/in.h"#include "../../net/netinet/if_ether.h"#include "../../net/netdnet/dli_var.h"#include "../../net/dli/csmacd_if.h"/* *		d l i _ s e t o p t * * Process a DLI request. * * Returns:		Error code if error, otherwise NULL. * * Inputs: *	uentry		= Pointer to the user's line table entry for this request. *	optbuf		= Buffer containg option. *	optlen		= Length of data in option buffer. *	optnam		= Name of option. */dli_setopt( uentry,optbuf,optlen,optnam ) register struct dli_line *uentry;register u_char *optbuf;short optlen;int optnam;{	u_short i, nmulti;	register int error;	register struct dli_sopt *option;	extern struct dli_line dli_ltable[];	struct protosw *pr;	option = &uentry->dli_sockopt;	/*	 * Make sure a device has been bound to, otherwise	 * operation would not make sense.	 */	if ( ! uentry->dli_if )	{		return(ENODEV);	}		/*	 * store option only if it is valid.	 */	switch (optnam)	{		case DLI_SET802CTL:			/*			 * store 802.3 control field			 * for isaps with class 1 service, validate it first			 */			if(uentry->dli_lineid.choose_addr.dli_802addr.svc == TYPE1)			{				if(optlen != 1)    /* only 1 byte ctl field allowed */					return(EINVAL);				if(uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ssap == SNAP_SAP && ((u_char)optbuf[0] != UI_NPCMD) )						return(EINVAL);				switch((u_char)optbuf[0])				{					case UI_NPCMD:					case TEST_PCMD:					case TEST_NPCMD:					case XID_PCMD:					case XID_NPCMD:						uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ctl.U_fmt = (u_char)optbuf[0];						break;					default:						return(EINVAL);				}			}			else    /* user service here */			{				if(optlen == 1) 					uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ctl.U_fmt = (u_char)optbuf[0];				else if(optlen == 2) 					uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ctl.I_S_fmt = (u_short)optbuf;				else return(EINVAL);			}			break;		case DLI_ENAGSAP:			/* 			 *enable a list of group saps for this isap			 */			if(uentry->dli_lineid.choose_addr.dli_802addr.svc == TYPE1)				return(ENOPROTOOPT);			/* find the matching line table entry */			for(i = 0; i < optlen; i++)			{				if((u_char)optbuf[i] < 3 || (u_char)optbuf[i] > 255 || 				!((u_char)optbuf[i] & 1))					return(EINVAL);				if(error = osi_ena_802gsap(uentry->dli_if, (u_char)optbuf[i], 				   uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ssap))					return(error);			}			break;		case DLI_DISGSAP:			/*			 * disable a list of group saps that 			 * that this isap has enabled			 */			for(i = 0; i < optlen; i++)			{				if( (u_char)optbuf[i] < 3 || (u_char)optbuf[i] > 255 || 				!((u_char)optbuf[i] & 1))					return(EINVAL);				if(error = osi_dis_802gsap(uentry->dli_if, (u_char)optbuf[i], 				   uentry->dli_lineid.choose_addr.dli_802addr.eh_802.ssap))					return(error);			}			break;		case DLI_STATE:			return(ENOPROTOOPT);			break;		case DLI_INTERNALOOP:			if ( optlen != 1 || (*optbuf != DLP_IOFF && *optbuf != DLP_ION))			{				return(ENOPROTOOPT);			}			option->dli_iloop = *optbuf;			break;		/*		 * Set multicast address(es). Verify correct number and		 * validity of addresses.		 */		case DLI_MULTICAST:			if ( (optlen % MCAST_SIZE) || ((nmulti = optlen/MCAST_SIZE) > MCAST_MAXNUM) )			{				return(ENOPROTOOPT);			}			for( i = 0; i < nmulti; i++ )			{				if( ! (optbuf[i*MCAST_SIZE] & 1) )				{					return(ENOPROTOOPT);				}			}			if ( error = mcast_cmd(option->dli_mcast, SIOCDELMULTI, uentry->dli_if, uentry->dli_proto, uentry->dli_portid) )			{				return(error);			}			bcopy(optbuf, option->dli_mcast, optlen);			if ( (error = mcast_cmd(option->dli_mcast, SIOCADDMULTI, uentry->dli_if, uentry->dli_proto, uentry->dli_portid)) )			{				mcast_cmd(option->dli_mcast, SIOCDELMULTI, uentry->dli_if, uentry->dli_proto, uentry->dli_portid);			}			return(error);			break;		default:			return(ENOPROTOOPT);			break;	}	return(NULL);}/* *		m c a s t _ c m d * * Add/delete multicast command.  This routine keeps an * accurate record of the multicast addresses it has enabled. * * Returns:		Status code from driver. * * Inputs: *	mcast_buf	= Buffer containing multicast address(es). *	cmd		= Command given to driver. *	ifp		= Pointer to ifnet structure to access driver. */mcast_cmd( mcast_buf,cmd,ifp, pr, portid ) register u_char *mcast_buf;register struct ifnet *ifp;int cmd;struct protosw *pr;u_int portid;{	struct ifreq dreq;	register int i;	register int error;	int saveaffinity;	for( i = 0; i < MCAST_ASIZE; i += MCAST_SIZE)	{		if ( *(mcast_buf+i) & 1 )		{			if ( pr == NULL || portid == 0 )			{				*(struct ether_pa *) dreq.ifr_addr.sa_data = *(struct ether_pa *) (mcast_buf+i);				CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity);				error = (*ifp->if_ioctl)(ifp, cmd, &dreq);				RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);			}			else			{				u_int opcode;				struct dli_ifmcast mc;				if ( cmd == SIOCDELMULTI )					opcode = CSMACD_DISMCAST;				else					opcode = CSMACD_ENAMCAST;				bzero(&mc, sizeof(mc));				mc.port = (caddr_t) portid;				bcopy((mcast_buf+i), mc.mcast, sizeof(mc.mcast));				error = (*pr->pr_ctloutput)(PRCO_PIF, NULL, 0, opcode, &mc);			}			if ( error )			{				if ( cmd == SIOCADDMULTI )				{					bzero(mcast_buf+i, (MCAST_ASIZE - i));				}				else				{					bcopy(mcast_buf+i, mcast_buf, (MCAST_ASIZE - i));					bzero(mcast_buf+(MCAST_ASIZE-i), i);				}				return(error);			}		}	}	if ( cmd == SIOCDELMULTI )	{		bzero(mcast_buf, MCAST_ASIZE);	}	return(NULL);}/* *		c h a n g e _ s t a t e * * * Returns:		Status code from driver. * * Inputs: *	ifp		= Pointer to ifnet structure to access driver. *	new_state	= User requested state (off, on, mop) *	state_var	= pointer to current state information *	old_state	= if addr, store current state information  */change_dlistate( ifp, new_state, state_var, old_state )register struct ifnet *ifp;register struct ifstate *new_state;register struct ifstate *state_var;register struct ifstate *old_state;{	int saveaffinity;   /* for nonsmp drivers.  8.18.88.us */	int status = 0;	if ( old_state )	{		old_state->if_family = ifp->if_addr.sa_family;		old_state->if_rdstate = IFS_RDSTATE;		old_state->if_wrstate = ~IFS_WRSTATE;		old_state->if_xferctl = ~IFS_XFERCTL;		CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity);		status = (*ifp->if_ioctl)(ifp, SIOCSTATE, old_state);		RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);		if (  status )		{			return(status);		}	}	new_state->if_family = AF_DLI;	if ( new_state->if_ustate == IFS_USRON )	{		new_state->if_nomuxhdr = IFS_NOMUXHDR;	}	new_state->if_wrstate = IFS_WRSTATE;	new_state->if_rdstate = IFS_RDSTATE;	CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity);	status = (*ifp->if_ioctl)(ifp, SIOCSTATE, new_state);	RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);	if (  ! (status ) )	{		*state_var = *new_state;	}	return(status);}

⌨️ 快捷键说明

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