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

📄 if_ni.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
	int off, resid;	struct ifqueue *inq;	/*	 * Deal with trailer protocol: if type is trailer	 * get true type from first 16-bit word past data.	 * Remember that type was trailer by setting off.	 */	if (swloop) {		eh = mtod(swloop, struct ether_header *);		swloop_eh = *eh;		eh = &swloop_eh;		if ( swloop->m_len > sizeof(struct ether_header))			m_adj(swloop, sizeof(struct ether_header));		else {			MFREE(swloop, swloop_tmp1);			if ( ! swloop_tmp1 )				return;			else				swloop = swloop_tmp1;		}	} else  	    eh = (struct ether_header *)(vaddr(bde));	eh->ether_type = ntohs((u_short)eh->ether_type);#define	dataaddr(eh, off, type)	((type)(((caddr_t)(eh)+(off))))	if (eh->ether_type >= ETHERTYPE_TRAIL &&	    eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {		off = (eh->ether_type - ETHERTYPE_TRAIL) * 512;		if (off >= ETHERMTU)			return;		/* sanity */		if (swloop) {			struct mbuf *mprev, *m0 = swloop;/* need to check this against off */			mprev = m0;			while (swloop->m_next){/*real header at end of chain*/				mprev = swloop;				swloop = swloop->m_next;			}			/* move to beginning of chain */			mprev->m_next = 0;			swloop->m_next = m0;			eh->ether_type = ntohs( *mtod(swloop, u_short *));		} else {			struct ether_header *peh;			peh = (struct ether_header *)vaddr(bde+1);			eh->ether_type = ntohs(*dataaddr(peh, off, u_short *));			resid = ntohs(*(dataaddr(peh, off+2, u_short *)));			if (off + resid > len)			return;		/* sanity */		}	} else		off = 0;	if (len == 0)		return;	/*	 * Pull packet off interface.  Off is nonzero if packet	 * has trailing header; niget will then force this header	 * information to be at the front, but we still have to drop	 * the type and length which are at the front of any trailer data.	 */	if (swloop) {		m = m_copy(swloop, 0, M_COPYALL);		m_freem(swloop);	} else {	/* Header was in the 1st buffer */		bde++;		/*		 * subtract the ethernet header AND checksum field length		 */		len -= sizeof(struct ether_header)+4;		m = niget(ni, bde, len, off);	}	if (m == 0)		return;	if (off) {		m->m_off += 2 * sizeof (u_short);		m->m_len -= 2 * sizeof (u_short);	}	/* Dispatch this packet */	net_read(&(ds->ds_ed), eh, m, len, (swloop != NULL), (off != 0));}/* * Process an ioctl request. */niioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	register struct ni_softc *ds = &ni_softc[ifp->if_unit];	register struct ni *ni = &niinfo[ifp->if_unit];	register struct nidevice *addr = (struct nidevice *)ni->ni_regs;	struct protosw *pr;	struct ifreq *ifr = (struct ifreq *)data;	struct ifdevea *ifd = (struct ifdevea *)data;	register struct ifaddr *ifa = (struct ifaddr *)data;	int s,t,z = splnet(), error = 0, empty;	switch (cmd) {        case SIOCENABLBACK:                ifp->if_flags |= IFF_LOOPBACK;                break;         case SIOCDISABLBACK:                ifp->if_flags &= ~IFF_LOOPBACK;                niinit(ifp->if_unit);                break;         case SIOCRPHYSADDR:                 /*                 * read default hardware address.                 */		s = splimp();		smp_lock(&ds->lk_ni_softc, LK_RETRY);		bcopy(ds->ds_dpaddr, ifd->default_pa, 6);		bcopy(ds->ds_addr, ifd->current_pa, 6);		smp_unlock(&ds->lk_ni_softc);		splx(s);                break; 	case SIOCSPHYSADDR: 		/* 		 * Set physaddr.		 */                niinit(ifp->if_unit);	{		struct ni_msg *ni_msg;		if((ni_msg = (struct ni_msg *)remqhi(&ni->freeq0, NI_MAXITRY))!= (struct ni_msg *)QEMPTY) {		ni_msg->opcode = SNDMSG;		ni_msg->status = 0;		ni_msg->ni_opcode = NIOP_WPARAM;		ni_msg->msg_len = sizeof (struct ni_param) + 6;		((struct ni_param *)&ni_msg->text[0])->flags = NI_PAD;		bcopy(ifr->ifr_addr.sa_data, 			((struct ni_param *)&ni_msg->text[0])->apa, 6);		bcopy(ifr->ifr_addr.sa_data, ds->ds_addr, 6);#if NPACKETFILTER > 0		/* tell packet filter about new address */		pfilt_newaddress(ds->ds_ed.ess_enetunit, ds->ds_addr);#endif NPACKETFILTER > 0		if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY))>0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN;		}		}	}		break;	case SIOCDELMULTI: 	case SIOCADDMULTI: 	{		int i,j = -1;		s = splimp();		smp_lock(&ds->lk_ni_softc, LK_RETRY);		if (cmd==SIOCDELMULTI) {		   for (i = 0; i < NMULTI; i++)		       if (bcmp(ds->ds_multi[i], ifr->ifr_addr.sa_data,MULTISIZE) == 0) {			    	if (--ds->ds_muse[i] == 0)					bcopy(ni_multi,ds->ds_multi[i],MULTISIZE);		       }		} else {		    for (i = 0; i < NMULTI; i++) {			if (bcmp(ds->ds_multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) {			    ds->ds_muse[i]++;			    smp_unlock(&ds->lk_ni_softc);			    splx(s);			    goto done;			}			if (bcmp(ds->ds_multi[i],ni_multi,MULTISIZE) == 0)			    j = i;		    }		    if (j == -1) {			printf("ni%d: multi failed, multicast list full: %d\n",				ni->unit, NMULTI);			error = ENOBUFS;			smp_unlock(&ds->lk_ni_softc);			splx(s);			goto done;		    }		    bcopy(ifr->ifr_addr.sa_data, ds->ds_multi[j], MULTISIZE);		    ds->ds_muse[j]++;		}	/* Update up Protocol Type Definition Block */		if(ifp->if_flags&IFF_UP)			ni_sptdb(ni,ETHERTYPE_IP,2,2,PTDB_UNK|PTDB_BDC,1);		smp_unlock(&ds->lk_ni_softc);		splx(s);		break;	}	case SIOCRDCTRS:	case SIOCRDZCTRS:		{		register struct ctrreq *ctr = (struct ctrreq *)data;	/* Read/Read-Clear counters */		struct ni_msg *ni_msg;		struct ni_counters *ni_counters;		int k;#ifdef vax		/*		 * If we're being called on the interrupt stack, we need		 * to return failure to avoid a sleep panic.		 */		if (movpsl() & PSL_IS) {			error = EINVAL;			goto done;		}#endif vax#ifdef mips		/* 		 * Currently no solution for mips. Need to fix this.		 */#endif mips		ni_msg = (struct ni_msg *)remqhi(&ni->freeq0, NI_MAXITRY);		if(ni_msg == (struct ni_msg *)QEMPTY) {			error = ENOBUFS;			goto done;		}		ni_msg->opcode = SNDMSG;		if(cmd == SIOCRDCTRS)			ni_msg->ni_opcode = NIOP_RDCNTR;		else			ni_msg->ni_opcode = NIOP_RCCNTR;		ni_msg->msg_len = sizeof(struct ni_counters) + 6;		while((addr->pc&PC_OWN))			;		k=splimp();		if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY))>0)			printf("insqti failed\n");		else if(empty == QEMPTY)			addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN;		/* Wait for read counters to finish */		sleep((caddr_t)ni_msg, PUSER);		splx(k);		ni_counters = (struct ni_counters *)&ni_msg->text[0];		bzero(&ctr->ctr_ctrs, sizeof(struct estat));		ctr->ctr_type = CTR_ETHER;		ctr->ctr_ether.est_seconds = ni_counters->last_zero;		ctr->ctr_ether.est_bytercvd = *(int *)ni_counters->bytes_rec;		ctr->ctr_ether.est_bytesent = *(int *)ni_counters->bytes_snt;		ctr->ctr_ether.est_mbytercvd = *(int *)ni_counters->mbytes_rec;		ctr->ctr_ether.est_blokrcvd = *(int *)ni_counters->frame_rec;		ctr->ctr_ether.est_bloksent = *(int *)ni_counters->frame_snt;		ctr->ctr_ether.est_mblokrcvd = *(int *)ni_counters->mframe_rec;		ctr->ctr_ether.est_deferred = *(int *)ni_counters->fs_def;		ctr->ctr_ether.est_single = *(int *)ni_counters->fs_sc;		ctr->ctr_ether.est_multiple = *(int *)ni_counters->fs_mc;		ctr->ctr_ether.est_sendfail = ni_counters->sfail;		ctr->ctr_ether.est_sendfail_bm = ni_counters->sfbm;		ctr->ctr_ether.est_collis = ni_counters->ctf;		ctr->ctr_ether.est_recvfail = ni_counters->rfail;		ctr->ctr_ether.est_recvfail_bm = ni_counters->rfbm;		ctr->ctr_ether.est_unrecog = ni_counters->unrec;		ctr->ctr_ether.est_overrun = ni_counters->datao;		ctr->ctr_ether.est_sysbuf = ni_counters->sbu;		ctr->ctr_ether.est_userbuf = ni_counters->ubu;		ctr->ctr_ether.est_mbytesent = *(int *)ni_counters->mbytes_snt;		ctr->ctr_ether.est_mbloksent = *(int *)ni_counters->mframe_snt;		}		break;	case SIOCSIFADDR:		{		ifp->if_flags |= IFF_UP;		niinit(ifp->if_unit);		switch(ifa->ifa_addr.sa_family) {#ifdef INET		case AF_INET:			t = splimp();			smp_lock(&lk_ifnet, LK_RETRY);			((struct arpcom *)ifp)->ac_ipaddr =				IA_SIN(ifa)->sin_addr;			smp_unlock(&lk_ifnet);			splx(t);			/* 1st packet out */			arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);			break;#endif		default:			if (pr=iffamily_to_proto(ifa->ifa_addr.sa_family)) {				error = (*pr->pr_ifioctl)(ifp, cmd, data);			}			break;		}		}		break;#ifdef IFF_PROMISC     /* IFF_ALLMULTI and NPACKETFILTER, as well */	case SIOCSIFFLAGS:		if (ifp->if_flags & IFF_UP) {			int newptdb = 0;			if ((ifp->if_flags & IFF_PROMISC) == IFF_PROMISC)				newptdb |= PTDB_PROM;			if ((ifp->if_flags & IFF_ALLMULTI) == IFF_ALLMULTI)				newptdb |= PTDB_AMC;			ni_sptdb(ni,ETHERTYPE_IP,2,2,PTDB_UNK|PTDB_BDC|newptdb,1);		}		break;#endif IFF_PROMISC	default:		error = EINVAL;	}done:	splx(z);	return (error);}/* * Pull read data off a interface. * Len is length of data, with local net header stripped. * Off is non-zero if a trailer protocol was used, and * gives the offset of the trailer information. * We copy the trailer information and then all the normal * data into mbufs. */struct mbuf *niget(ni, bde, totlen, trailoff)	struct ni *ni;	struct _bd *bde;	int totlen, trailoff;{	struct mbuf *top, **mp, *m;	int off = trailoff, len = 0;	/* setup for 1st buffer */	int cp = (int) vaddr(bde); 	int bdelen = bde->buf_len;	top = 0;	mp = &top;	while (totlen > 0) {		MGET(m, M_DONTWAIT, MT_DATA);		if (m == 0)			goto bad;		if (off) {			cp = (int) vaddr(bde) + trailoff;			bdelen = bde->buf_len;			len = totlen - off;		} else			len = totlen;		if (bdelen >= CLBYTES && len >= CLBYTES) {			struct mbuf *p;			struct pte *cpte, *ppte;			int i;			char *newdata;			if (!claligned(cp))				goto copy;			KM_ALLOC(newdata, char *, M_CLUSTERSZ, KM_CLUSTER, KM_NOWAIT);			if (newdata == 0)				goto nopage;			MCLPUT(m, cp);			m->m_len = len;			bde->pt_addr = svtopte(newdata);			bde->offset = (unsigned)newdata&PGOFSET;			bde->buf_len = NI_MAXPACKETSZ;			goto nocopy;		}nopage:		m->m_len = MIN(MLEN, len);		m->m_len = MIN(m->m_len, bdelen);		m->m_off = MMINOFF;copy:		bcopy((caddr_t)cp, mtod(m, caddr_t), (unsigned)m->m_len);		cp += m->m_len;nocopy:		bdelen -= m->m_len;		*mp = m;		mp = &m->m_next;		if (off) {			/* sort of an ALGOL-W style for statement... */			off += m->m_len;			if (off == totlen) {				cp = (int) vaddr(bde);				bdelen = bde->buf_len;				off = 0;				totlen = trailoff;			}		} else			totlen -= m->m_len;	}	return (top);bad:	m_freem(top);	return (0);}ni_sptdb(ni, type, index, q, flags, doclear)	struct ni *ni;	/* Set Protocol Type Definition Block */{		register struct ni_softc *ds = &ni_softc[ni->unit];		struct ni_msg *ni_msg;		struct ptdb *ptdb;		int empty,i;		struct nidevice *addr = (struct nidevice *)ni->ni_regs;		int clear = doclear;loop:		ni_msg = (struct ni_msg *)remqhi(&ni->freeq0, NI_MAXITRY);		if(ni_msg == (struct ni_msg *)QEMPTY)			return;		bzero(&ni_msg->text[0], sizeof(struct ptdb));		ni_msg->status = 0;		if(clear)			ni_msg->ni_opcode = NIOP_CLPTDB;		else			ni_msg->ni_opcode = NIOP_STPTDB;		ni_msg->opcode = SNDMSG;		ptdb = (struct ptdb *)&ni_msg->text[0];		ptdb->flags = flags;		ptdb->fq_index = q;		ptdb->ptt = type;		ptdb->ptdb_index = index;		ptdb->adr_len = 0;		ni_msg->msg_len = 18;		if(!clear && flags&(PTDB_AMC|PTDB_BDC)) {		   int nptdb=0;		/* 1st reserved for -1 broadcast addr */					   ptdb->adr_len++;		   ni_msg->msg_len += 8;		   bcopy(ni_multi, (&ptdb->multi[nptdb++])->addr,6);		   for (i = 0; i < NMULTI - 1; i++)		        if (ds->ds_muse[i] > 0) {			ptdb->adr_len++;			ni_msg->msg_len += 8;			bcopy(ds->ds_multi[i],(&ptdb->multi[nptdb++])->addr,6);		       }		}		if((empty=insqti(ni_msg, &ni->comq0, NI_MAXITRY)) > 0)			printf("insqti failed\n");		else if(empty == QEMPTY) {			while((addr->pc&PC_OWN))				;			addr->pc = PC_CMDQNE|PC_CMDQ0|PC_OWN;			while((addr->pc&PC_OWN))				;		} else 			while((addr->pc&PC_OWN))				;		if(clear) {			clear = 0;			goto loop;		}}	#endif

⌨️ 快捷键说明

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