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

📄 if_imp.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
		IF_DROP(inq);		goto drop;	}	IF_ENQUEUE(inq, m);	return;drop:	m_freem(m);}/* * Bring the IMP down after notification. */impdown(sc)	struct imp_softc *sc;{	int s = splimp();	sc->imp_state = IMPS_DOWN;	impmsg(sc, "marked down");	hostreset(((struct in_ifaddr *)&sc->imp_if.if_addrlist)->ia_net);	if_down(&sc->imp_if);	splx(s);}/*VARARGS*/impmsg(sc, fmt, a1, a2, a3)	struct imp_softc *sc;	char *fmt;	u_int a1;{	printf("imp%d: ", sc->imp_if.if_unit);	printf(fmt, a1, a2, a3);	printf("\n");}/* * Process an IMP "error" message, passing this * up to the higher level protocol. */impnotify(what, cp, hp, ifp)	int what;	struct control_leader *cp;	struct host *hp;	struct ifnet *ifp;		/* BRL */{	struct in_addr in;	imp_leader_to_addr(&in, (struct imp_leader *)cp, ifp);  /* BRL */	if (cp->dl_link != IMPLINK_IP)		raw_ctlinput(what, (caddr_t)&in);	else		pfctlinput(what, (caddr_t)&in);	if (hp) {		hp->h_flags |= (1 << what);		hostfree(hp);		hp->h_timer = HOSTDEADTIMER;	}}/* * ARPAnet 1822 output routine. * Called from higher level protocol routines to set up messages for * transmission to the imp.  Sets up the header and calls impsnd to * enqueue the message for this IMP's hardware driver. */impoutput(ifp, m0, dst)	register struct ifnet *ifp;	struct mbuf *m0;	struct sockaddr *dst;{	register struct imp_leader *imp;	register struct mbuf *m = m0;	int dlink, len;	int error = 0;	/*	 * Don't even try if the IMP is unavailable.	 */	if (imp_softc[ifp->if_unit].imp_state != IMPS_UP) {		error = ENETDOWN;		goto drop;	}	switch (dst->sa_family) {#ifdef INET	case AF_INET: {		struct ip *ip = mtod(m0, struct ip *);		struct sockaddr_in *sin = (struct sockaddr_in *)dst;		dlink = IMPLINK_IP;		len = ntohs((u_short)ip->ip_len);		break;	}#endif	case AF_IMPLINK:		goto leaderexists;	default:		printf("imp%d: can't handle af%d\n", ifp->if_unit, 			dst->sa_family);		error = EAFNOSUPPORT;		goto drop;	}	/*	 * Add IMP leader.  If there's not enough space in the	 * first mbuf, allocate another.  If that should fail, we	 * drop this sucker.	 */	if (m->m_off > MMAXOFF ||	    MMINOFF + sizeof(struct imp_leader) > m->m_off) {		m = m_get(M_DONTWAIT, MT_DATA);		if (m == 0) {			error = ENOBUFS;			goto drop;		}		m->m_next = m0;		m->m_len = sizeof(struct imp_leader);	} else {		m->m_off -= sizeof(struct imp_leader);		m->m_len += sizeof(struct imp_leader);	}	imp = mtod(m, struct imp_leader *);	imp->il_format = IMP_NFF;	imp->il_mtype = IMPTYPE_DATA;	imp_addr_to_leader(imp,		((struct sockaddr_in *)dst)->sin_addr.s_addr); /* BRL */	imp->il_length = htons((u_short)len << 3);		/* BRL */	imp->il_link = dlink;	imp->il_flags = imp->il_htype = imp->il_subtype = 0;leaderexists:	return (impsnd(ifp, m));drop:	m_freem(m0);	return (error);}/*  * Put a message on an interface's output queue.  * Perform RFNM counting: no more than 8 message may be * in flight to any one host. */impsnd(ifp, m)             	struct ifnet *ifp;	struct mbuf *m;{	register struct imp_leader *ip;	register struct host *hp;	struct impcb *icp;	int s, error;	ip = mtod(m, struct imp_leader *);	/*	 * Do RFNM counting for data messages	 * (no more than 8 outstanding to any host)	 */ 	s = splimp();	if (ip->il_mtype == IMPTYPE_DATA) {		struct in_addr addr;		imp_leader_to_addr(&addr, ip, ifp);	/* BRL */		if ((hp = hostlookup(addr)) == 0)			hp = hostenter(addr);		if (hp && (hp->h_flags & (HF_DEAD|HF_UNREACH))) {			error = hp->h_flags&HF_DEAD ? EHOSTDOWN : EHOSTUNREACH;			hp->h_timer = HOSTDEADTIMER;			hp->h_flags &= ~HF_INUSE;			goto bad;		}		/*		 * If IMP would block, queue until RFNM		 */		if (hp) {#ifndef NORFNM					/* BRL */			if (hp->h_rfnm < 8)#endif			{				hp->h_rfnm++;				goto enque;			}			if (hp->h_qcnt < 8) {	/* high water mark */				HOST_ENQUE(hp, m);				goto start;			}		}		error = ENOBUFS;		goto bad;	}enque:	if (IF_QFULL(&ifp->if_snd)) {		IF_DROP(&ifp->if_snd);		error = ENOBUFS;bad:		m_freem(m);		splx(s);		return (error);	}	IF_ENQUEUE(&ifp->if_snd, m);start:	icp = &imp_softc[ifp->if_unit].imp_cb;	if (icp->ic_oactive == 0)		(*icp->ic_start)(ifp->if_unit);	splx(s);	return (0);}/* * Put three 1822 NOOPs at the head of the output queue.  * Part of host-IMP initialization procedure. * (Should return success/failure, but noone knows * what to do with this, so why bother?) * This routine is always called at splimp, so we don't * protect the call to IF_PREPEND. */impnoops(sc)             	register struct imp_softc *sc;{	register i;	register struct mbuf *m;	register struct control_leader *cp;	sc->imp_dropcnt = IMP_DROPCNT;	for (i = 0; i < IMP_DROPCNT + 1; i++) { 		if ((m = m_getclr(M_DONTWAIT, MT_DATA)) == 0) 			return;		m->m_len = sizeof(struct control_leader);		cp = mtod(m, struct control_leader *);		cp->dl_format = IMP_NFF;                cp->dl_link = i;                cp->dl_mtype = IMPTYPE_NOOP;		IF_PREPEND(&sc->imp_if.if_snd, m);	}	if (sc->imp_cb.ic_oactive == 0)		(*sc->imp_cb.ic_start)(sc->imp_if.if_unit);}/* * Process an ioctl request. */impioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	struct ifaddr *ifa = (struct ifaddr *) data;	int s = splimp(), error = 0;	switch (cmd) {	case SIOCSIFADDR:		if (ifa->ifa_addr.sa_family != AF_INET) {			error = EINVAL;			break;		}		if ((ifp->if_flags & IFF_RUNNING) == 0)			impinit(ifp->if_unit);		break;	default:		error = EINVAL;	}	splx(s);	return (error);}#ifdef IMPLEADERSprintleader(routine, ip)	char *routine;	register struct imp_leader *ip;{	printf("%s: ", routine);	printbyte((char *)ip, 12);	printf("<fmt=%x,net=%x,flags=%x,mtype=", ip->il_format, ip->il_network,		ip->il_flags);	if (ip->il_mtype <= IMPTYPE_READY)		printf("%s,", impleaders[ip->il_mtype]);	else		printf("%x,", ip->il_mtype);	printf("htype=%x,host=%x,imp=%x,link=", ip->il_htype, ip->il_host,		ntohs(ip->il_imp));	if (ip->il_link == IMPLINK_IP)		printf("ip,");	else		printf("%x,", ip->il_link);	printf("subtype=%x,len=%x>\n",ip->il_subtype,ntohs(ip->il_length)>>3);}printbyte(cp, n)	register char *cp;	int n;{	register i, j, c;	for (i=0; i<n; i++) {		c = *cp++;		for (j=0; j<2; j++)			putchar(0,"0123456789abcdef"[(c>>((1-j)*4))&0xf],0);		putchar(0,' ',0);	}	putchar(0,'\n',0);}#endif/* * Routine to convert from IMP Leader to InterNet Address. * * This procedure is necessary because IMPs may be assigned Class A, B, or C * network numbers, but only have 8 bits in the leader to reflect the * IMP "network number".  The strategy is to take the network number from * the ifnet structure, and blend in the host-on-imp and imp-on-net numbers * from the leader. * * There is no support for "Logical Hosts". * * Class A:	Net.Host.0.Imp * Class B:	Net.net.Host.Imp * Class C:	Net.net.net.(Host4|Imp4) */imp_leader_to_addr(ap, ip, ifp)	struct in_addr *ap;	register struct imp_leader *ip;	struct ifnet *ifp;{	register long final;	struct in_ifaddr *ia;	register struct sockaddr_in *sin;	int imp = htons(ip->il_imp);	sin = (struct sockaddr_in *)(&ifp->if_addrlist->ifa_addr);	final = htonl(sin->sin_addr.s_addr);	if (IN_CLASSA(final)) {		final &= IN_CLASSA_NET;		final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<16);	} else if (IN_CLASSB(final)) {		final &= IN_CLASSB_NET;		final |= (imp & 0xFF) | ((ip->il_host & 0xFF)<<8);	} else {		final &= IN_CLASSC_NET;		final |= (imp & 0x0F) | ((ip->il_host & 0x0F)<<4);	}	ap->s_addr = htonl(final);}/* * Function to take InterNet address and fill in IMP leader fields. */imp_addr_to_leader(imp, a)	register struct imp_leader *imp;	long a;{	register long addr = htonl(a);		/* host order */	imp->il_network = 0;	/* !! */	if (IN_CLASSA(addr)) {		imp->il_host = ((addr>>16) & 0xFF);		imp->il_imp = addr & 0xFF;	} else if (IN_CLASSB(addr)) {		imp->il_host = ((addr>>8) & 0xFF);		imp->il_imp = addr & 0xFF;	} else {		imp->il_host = ((addr>>4) & 0xF);		imp->il_imp = addr & 0xF;	}	imp->il_imp = htons(imp->il_imp);	/* network order! */}#endif

⌨️ 快捷键说明

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