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

📄 dli_subr.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    else    {	if ( eh->len < len && len == DLI_MINPKT )	    m_adj(m->m_next, -(len - eh->len));    }#endif    cp = mtod(m->m_next, u_char *);   /* remove up to ctl fld */    eh->dsap = *cp++;    eh->ssap = *cp++;    m_adj(m->m_next, 2);         eh->len -= 2;    for(i = 0; i < MAX_BROADCSTDEV; i++)   /* look for matching device */    {	/*	 * Don't need to take out lock since this member is	 * read-only after the system is booted.	 */	if(if_isapt[i].ifp != rcv->rcv_ifp)	    continue;	/* grab possible socket and service class info now */	if ( (eh->dsap & 1) == NULL && eh->dsap != NULL && eh->dsap != SNAP_SAP )	{	    smp_lock(&lk_dli, LK_RETRY);	    svc = if_isapt[i].svc[(eh->dsap>>4)];	    so = if_isapt[i].so[eh->dsap>>VSAP];	    smp_unlock(&lk_dli);	}	if(eh->dsap == NULL || eh->dsap == SNAP_SAP)	{	    /*	     * special case is DSAP = NULL or SNAP_SAP 	     */	    if(((eh->ctl.U_fmt = (u_char)*cp++)& 3) != 3)		goto dropit;	    m_adj(m->m_next, 1);      /* pull ctrl field */	    --eh->len;	    if(eh->ctl.U_fmt == UI_NPCMD)  /* save pi for snap */	    {		if(eh->dsap == NULL)		    goto dropit;		for(i = 0; i < 5; i++)		    eh->osi_pi[i] = *cp++;		m_adj(m->m_next, 5);      /* pull protocol */		eh->len -= 5;	    }	    osi_proc_ctl(m,so,rcv);	    return;	}	else if(so != NULL )	{	    /* handle DSAP = isaps */	    bit = 1 << ( (eh->dsap>>VSAP) % 8);	    if(svc & bit)	    { 		/* for class 1 service get ctl field */		if( (eh->ctl.U_fmt = (u_char)*cp) & 3 != 3)		    goto dropit;		m_adj(m->m_next, 1);    		--eh->len;		osi_proc_ctl(m,so,rcv);		return;	    }	    else	    {		/*		 * must be users supplied service, just pass it all up,		 * but leave ctl in with data		 */		switch(*cp & 3)		{		    case 0:        /* information */		    case 1:        /* supervisory */		    case 2:        /* information */			eh->ctl.I_S_fmt = (u_short)*cp;			break;		    case 3:        /* unnumbered */			eh->ctl.U_fmt = (u_char)*cp;			break;		    default:			goto dropit;		}			   		if ( (ue = dli_getlte_notrust(so)) != NULL )		{		    found_user(m, so, DLI_802, rcv);		    smp_unlock(&so->lk_socket);		    smp_unlock(&ue->dli_lk);		}		else		    m_freem(m);		return;	    }	}	else if( eh->dsap & 1 )  	{	    /*	     * The only thing left should be gsaps in user supplied mode.	     * Try and get a copy of the packet for each sap that has the 	     * gsap enabled. If any fail, free any copies and the original 	     */	    smp_lock(&lk_dli, LK_RETRY);	    if ( ffs(*(long *) &if_isapt[i].gsap[(eh->dsap>>VSAP)][0]) || 		  	  ffs(*(long *) &if_isapt[i].gsap[(eh->dsap>>VSAP)][4]) || 		 	  ffs(*(long *) &if_isapt[i].gsap[(eh->dsap>>VSAP)][8]) || 			  ffs(*(long *) &if_isapt[i].gsap[(eh->dsap>>VSAP)][12]) )	    {		/* search gsap table for any isaps with this gsap enabled */		bit = 0;		cnt = 0;		for(j = 0; j < NISAPS / 8; j++)		{		byte = if_isapt[i].gsap[eh->dsap>>VSAP][j];		    /* if bit is set, bit pos = isap with this gsap enabled */		    for(k = 0; k < 8; k++)		    {			if(byte & 1)			{			    if(!(m_ar[cnt].m = m_copy(m, 0, M_COPYALL))){				while(--cnt >= 0)				    m_freem(m_ar[cnt].m);				smp_unlock(&lk_dli);				goto dropit;                 /* drop original */			    }			    m_ar[cnt].so = if_isapt[i].so[bit];			    m_ar[cnt++].sap = bit;			}			++bit;			byte >>= 1;		    }		}		smp_unlock(&lk_dli);		m_freem(m->m_next);             /* done with original */		while(--cnt >= 0) {		    if ( (ue = dli_getlte_notrust(m_ar[cnt].so)) != NULL )		    {			found_user(m_ar[cnt].m, m_ar[cnt].so, DLI_802, rcv);			smp_unlock(&(m_ar[cnt].so->lk_socket));			smp_unlock(&ue->dli_lk);		    }		    else			m_freem(m_ar[cnt].m);		}		m_free(m);		return;	    }	    else	    	smp_unlock(&lk_dli);	}	goto dropit;    }dropit:    if(m)	m_freem(m);    return;}/* * process the control field on incoming packets * for class 1 service only * the packet header must have been adjusted by now */osi_proc_ctl(m,so, rcv)struct mbuf *m;struct socket *so;struct dli_recv *rcv;{    u_char dsap;    int len;    struct dli_line *ue, *dli_getlte_notrust();    dsap = rcv->rcv_hdr.osi_header.dsap;    /* only ctl allowed for class 1 */    switch(rcv->rcv_hdr.osi_header.ctl.U_fmt)       {	case XID_PCMD:	case XID_NPCMD:	case TEST_PCMD:	case TEST_NPCMD:	    if( rcv->rcv_hdr.osi_header.ssap & 1) /* got a response */	    {		switch(dsap)		{		    case NULL:   /* nobody to pass response to */		    case SNAP_SAP:			if(m) m_freem(m);			return;		    default:			if ( (ue = dli_getlte_notrust(so)) != NULL )			{			    found_user(m, so, DLI_802, rcv);			    smp_unlock(&ue->dli_lk);			    smp_unlock(&so->lk_socket);			}			else			{			    if ( m )			    	m_freem(m);			}			return;		}	    }	    else                     /* command, gotta respond for these guys */	    {		osi_rspndr(m, rcv);		return;	    }	case UI_NPCMD:                /* only type of ui */	    switch (dsap)	    {		case NULL:			if(m) m_freem(m);			return;		case SNAP_SAP:			forward_to_user(m, rcv);			return;		default:              /* got somebody */			if ( (ue = dli_getlte_notrust(so)) != NULL )			{			    found_user(m, so, DLI_802, rcv);			    smp_unlock(&ue->dli_lk);			    smp_unlock(&so->lk_socket);			}			else			{			    if ( m )			    	m_freem(m);			}			return;	    }	default:                      /* throw it out */	    if(m) m_freem(m);	    return;    }  }/* * respond to xid or test packet for class 1* service, for the null sap or the snap sap only* * input	packet as a chain of mbuf's, 1st mbuf garbage* return nothing, attempt is made to tx packet (no guarantees)*/osi_rspndr(m, rcv)struct mbuf *m;struct dli_recv *rcv;{	u_char *cp;	u_short len;	struct osi_802hdr *eh = &rcv->rcv_hdr.osi_header;	struct sockaddr_dl out_addr; 	struct mbuf *m0, *temp, *osi_buildhdr();	struct ifnet *ifp = rcv->rcv_ifp;	int saveaffinity;	/* got to do this for output routine */	bzero(&out_addr, sizeof(struct sockaddr_dl));	out_addr.dli_family = AF_DLI;	out_addr.dli_substructype = DLI_802;	out_addr.choose_addr.dli_802addr.svc = TYPE1;	out_addr.dli_device.dli_devnumber = ifp->if_unit;	len = strlen(ifp->if_name);	bcopy(ifp->if_name, out_addr.dli_device.dli_devname, len);	bcopy(rcv->rcv_hdr.osi_header.src, out_addr.choose_addr.dli_802addr.eh_802.dst, DLI_EADDRSIZE);	/* return it with the response bit set */	out_addr.choose_addr.dli_802addr.eh_802.ssap = eh->dsap | (u_char)1; 	out_addr.choose_addr.dli_802addr.eh_802.dsap = eh->ssap;	switch(eh->ctl.U_fmt & 0xEF)	{		case XID:			if(eh->len != 3)				goto bad;			cp = mtod(m, u_char *);			PUT8B(cp, 0x81);              			PUT8B(cp, 0x01);			PUT8B(cp, NULL);			m->m_len = 3;			m_freem(m->m_next);          /* don't need the rest */			m->m_next = NULL;			break;		case TEST:   /* just turn it around, they may have sent data */			m = m_free(m);         /* 1st mbuf has garbage */			break;		default:			goto bad;	}	/*	 * just have to return the control field	 */	out_addr.choose_addr.dli_802addr.eh_802.ctl.U_fmt = eh->ctl.U_fmt;	if(m0 = osi_buildhdr(&out_addr))	{		m0->m_next = m;		CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity);		(*ifp->if_output)(ifp, m0, &out_addr); 		RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity);		return;	}bad:	if(m)	    m_freem(m);	return;}/* *		d l i _ g e t l t e _ n o t r u s t 	 * * This routine returns a line table entry as a function * of a socket.  The line table entries are individually * inspected since we don't trust the socket pointer. * In addition, before returning, the locks for the line table  * entry and the socket are asserted if the routine  * succeeds. * * Note:  The socket lock musn't be asserted! * * Outputs:		Nothing. * * Inputs:		so = pointer to a socket. * * Returns:		pointer to a line table entry if success, *			otherwise NULL is returned. * */struct dli_line *dli_getlte_notrust(so)register struct socket *so;{	register int i;	register struct dli_line *ue = NULL;	if ( so == NULL )		return(NULL);	for ( i = 0; i < dli_maxline; i++ )	{		smp_lock(&dli_ltable[i].dli_lk, LK_RETRY);		if ( dli_ltable[i].dli_so == so )		{			ue = &dli_ltable[i];			smp_lock(&(dli_ltable[i].dli_so->lk_socket), LK_RETRY);			break;		}		smp_unlock(&dli_ltable[i].dli_lk);	}	return(ue);}/* *		d l i _ g e t l t e _ t r u s t 	 * * This routine returns a line table entry as a function * of a socket.  The line table entry is storeed as a * back pointer in the socket structure.  Since this is used, * the socket must be locked before calling this routine. * In addition, before returning, the locks for the line table  * entry and the socket are asserted if routine succeeds.  * If routine fails, nothing is asserted. * * Note:  The socket lock must be asserted! * * Outputs:		Nothing. * * Inputs:		so = pointer to a socket. * * Returns:		pointer to a line table entry, if valid, *			otherwise NULL. * */struct dli_line *dli_getlte_trust(so)register struct socket *so;{	register struct dli_line *ue = (struct dli_line *) so->so_pcb;	if ( so == NULL )		return(NULL);	smp_unlock(&so->lk_socket);	smp_lock(&ue->dli_lk, LK_RETRY);	if ( ue->dli_so == so )	{		smp_lock(&so->lk_socket, LK_RETRY);		return(ue);	}	else	{		smp_unlock(&ue->dli_lk);		return(NULL);	}}/* *		m a t c h _ m c a s t * * This routine looks at the destination address, and if it is * multicast, it checks to see if the address matches the user's * multicast addresses.  Note that if the user hasn't specified * any, the test fails. * * Outputs:		NULL if no match, otherwise 1. * * Inputs:		mcast1 = string containing Ethernet dest address. * 			mcast2 = string containing user's multicast address(es). */match_mcast( mcast2, mcast1 )register u_char *mcast2, *mcast1;{	register int i;	/*	 * If destination addr not multicast, pass test.	 */		if ( !(mcast1[0] & 1) )	{		return(1);	}	/*	 * If multicast, perform test.	 */	for( i = 0; i < MCAST_ASIZE; i += MCAST_SIZE)	{		if ( bcmp(mcast1, mcast2+i, MCAST_SIZE) == NULL )		{			return(1);		}	}		return(NULL);}/* *		m a t c h _ t a r g e t s * * check to see if a pair of ethernet addresses match * * Returns:		Error code if match occurs, otherwise NULL. * * Inputs: *	target1		= first ethernet address *	target2		= second ethernet address */match_targets(target1, target2)u_char *target1, *target2;{	if ( bcmp(target1, target2, DLI_EADDRSIZE) == NULL )	{		return(EADDRINUSE);	}	return(NULL);}#ifndef IFT_FDDI/* *		m _ l e n g t h * * Compute the number of bytes in a (non-empty) MBUF chain. * * Returns:		The number of bytes in the chain. * * Inputs: *	m		= Pointer to the MBUF chain. */m_length( m )register struct mbuf *m;{    register int len = 0;    if (m) do    {	len += m->m_len;    }    while (m = m->m_next);    return (len);}#endif

⌨️ 快捷键说明

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