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

📄 esis.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		IFDEBUG(D_ESISINPUT)			printf("esis_eshinput: esh: ht %d, naddr %d nsellength %d\n",					ht, naddr, nsellength);		ENDDEBUG		while (naddr-- > 0) {			struct iso_addr *nsap2; u_char *buf2;			ESIS_EXTRACT_ADDR(nsap, buf);			/* see if there is at least one more nsap in ESH differing			   only by nsel */			if (nsellength != 0) for (buf2 = buf; buf2 < buflim;) {				ESIS_EXTRACT_ADDR(nsap2, buf2);				IFDEBUG(D_ESISINPUT)					printf("esis_eshinput: comparing %s ", 						clnp_iso_addrp(nsap));					printf("and %s\n", clnp_iso_addrp(nsap2));				ENDDEBUG				if (Bcmp(nsap->isoa_genaddr, nsap2->isoa_genaddr,						 nsap->isoa_len - nsellength) == 0) {					nlen = nsellength;					break;				}			}			new_entry |= snpac_add(shp->snh_ifp,									nsap, shp->snh_shost, SNPA_ES, ht, nlen);			nlen = 0;		}	}	IFDEBUG(D_ESISINPUT)		printf("esis_eshinput: nsap %s is %s\n", 			clnp_iso_addrp(nsap), new_entry ? "new" : "old");	ENDDEBUG	if (new_entry && (iso_systype & SNPA_IS))		esis_shoutput(shp->snh_ifp, ESIS_ISH, esis_holding_time,						shp->snh_shost, 6, (struct iso_addr *)0);bad:	return;}/* * FUNCTION:		esis_ishinput * * PURPOSE:			process an incoming ISH pdu * * RETURNS:			 * * SIDE EFFECTS:	 * * NOTES:			 */esis_ishinput(m, shp)struct mbuf		*m;	/* esh pdu */struct snpa_hdr	*shp;	/* subnetwork header */{	struct esis_fixed	*pdu = mtod(m, struct esis_fixed *);	u_short				ht, newct;			/* holding time */	struct iso_addr		*nsap; 				/* Network Entity Title */	register u_char		*buf = (u_char *) (pdu + 1);	register u_char		*buflim = pdu->esis_hdr_len + (u_char *)pdu;	int					new_entry;	esis_stat.es_ishrcvd++;	CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);	IFDEBUG(D_ESISINPUT)		printf("esis_ishinput: ish: ht %d\n", ht);	ENDDEBUG	if (ESHonly)		goto bad;	ESIS_EXTRACT_ADDR(nsap, buf);	while (buf < buflim) {		switch (*buf) {		case ESISOVAL_ESCT:			if (iso_systype & SNPA_IS)				break;			if (buf[1] != 2)				goto bad;			CTOH(buf[2], buf[3], newct);			if (esis_config_time != newct) {				untimeout(esis_config,0);				esis_config_time = newct;				esis_config();			}			break;				default:			printf("Unknown ISH option: %x\n", *buf);		}		ESIS_NEXT_OPTION(buf);	}	new_entry = snpac_add(shp->snh_ifp, nsap, shp->snh_shost, SNPA_IS, ht, 0);	IFDEBUG(D_ESISINPUT)		printf("esis_ishinput: nsap %s is %s\n", 			clnp_iso_addrp(nsap), new_entry ? "new" : "old");	ENDDEBUG	if (new_entry)		esis_shoutput(shp->snh_ifp, 			iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH,			esis_holding_time, shp->snh_shost, 6, (struct iso_addr *)0);bad:	return;}/* * FUNCTION:		esis_rdinput * * PURPOSE:			Process an incoming RD pdu * * RETURNS:			 * * SIDE EFFECTS:	 * * NOTES:			 */esis_rdinput(m0, shp)struct mbuf		*m0;	/* esh pdu */struct snpa_hdr	*shp;	/* subnetwork header */{	struct esis_fixed	*pdu = mtod(m0, struct esis_fixed *);	u_short				ht;		/* holding time */	struct iso_addr		*da, *net = 0, *netmask = 0, *snpamask = 0;	register struct iso_addr *bsnpa;	register u_char		*buf = (u_char *)(pdu + 1);	register u_char		*buflim = pdu->esis_hdr_len + (u_char *)pdu;	esis_stat.es_rdrcvd++;	/* intermediate systems ignore redirects */	if (iso_systype & SNPA_IS)		return;	if (ESHonly)		return;	CTOH(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);	if (buf >= buflim)		return;	/* Extract DA */	ESIS_EXTRACT_ADDR(da, buf);	/* Extract better snpa */	ESIS_EXTRACT_ADDR(bsnpa, buf);	/* Extract NET if present */	if (buf < buflim) {		if (*buf == 0)			buf++; /* no NET present, skip NETL anyway */		else			ESIS_EXTRACT_ADDR(net, buf);	}	/* process options */	while (buf < buflim) {		switch (*buf) {		case ESISOVAL_SNPAMASK:			if (snpamask) /* duplicate */				return;			snpamask = (struct iso_addr *)(buf + 1);			break;		case ESISOVAL_NETMASK:			if (netmask) /* duplicate */				return;			netmask = (struct iso_addr *)(buf + 1);			break;		default:			printf("Unknown option in ESIS RD (0x%x)\n", buf[-1]);		}		ESIS_NEXT_OPTION(buf);	}	IFDEBUG(D_ESISINPUT)		printf("esis_rdinput: rd: ht %d, da %s\n", ht, clnp_iso_addrp(da));		if (net)			printf("\t: net %s\n", clnp_iso_addrp(net));	ENDDEBUG	/*	 *	If netl is zero, then redirect is to an ES. We need to add an entry	 *	to the snpa cache for (destination, better snpa).	 *	If netl is not zero, then the redirect is to an IS. In this	 *	case, add an snpa cache entry for (net, better snpa).	 *	 *	If the redirect is to an IS, add a route entry towards that	 *	IS.	 */	if (net == 0 || net->isoa_len == 0 || snpamask) {		/* redirect to an ES */		snpac_add(shp->snh_ifp, da,				bsnpa->isoa_genaddr, SNPA_ES, ht, 0);	} else {		snpac_add(shp->snh_ifp, net,				bsnpa->isoa_genaddr, SNPA_IS, ht, 0);		snpac_addrt(shp->snh_ifp, da, net, netmask);	}bad: ;    /* Needed by ESIS_NEXT_OPTION */}/* * FUNCTION:		esis_config * * PURPOSE:			Report configuration * * RETURNS:			 * * SIDE EFFECTS:	 * * NOTES:			Called every esis_config_time seconds */voidesis_config(){	register struct ifnet	*ifp;	timeout(esis_config, (caddr_t)0, hz * esis_config_time);	/* 	 *	Report configuration for each interface that 	 *	- is UP	 *	- has BROADCAST capability	 *	- has an ISO address	 */	/* Todo: a better way would be to construct the esh or ish	 * once and copy it out for all devices, possibly calling	 * a method in the iso_ifaddr structure to encapsulate and	 * transmit it.  This could work to advantage for non-broadcast media	 */		for (ifp = ifnet; ifp; ifp = ifp->if_next) {		if ((ifp->if_flags & IFF_UP) &&		    (ifp->if_flags & IFF_BROADCAST)) {			/* search for an ISO address family */			struct ifaddr	*ia;			for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {				if (ia->ifa_addr->sa_family == AF_ISO) {					esis_shoutput(ifp, 						iso_systype & SNPA_ES ? ESIS_ESH : ESIS_ISH,						esis_holding_time,						(caddr_t)(iso_systype & SNPA_ES ? all_is_snpa : 						all_es_snpa), 6, (struct iso_addr *)0);					break;				}			}		}	}}/* * FUNCTION:		esis_shoutput * * PURPOSE:			Transmit an esh or ish pdu * * RETURNS:			nothing * * SIDE EFFECTS:	 * * NOTES:			 */esis_shoutput(ifp, type, ht, sn_addr, sn_len, isoa)struct ifnet	*ifp;int				type;short			ht;caddr_t 		sn_addr;int				sn_len;struct	iso_addr *isoa;{	struct mbuf			*m, *m0;	caddr_t				cp, naddrp;	int					naddr = 0;	struct esis_fixed	*pdu;	struct iso_ifaddr	*ia;	int					len;	struct sockaddr_iso	siso;	if (type == ESIS_ESH)		esis_stat.es_eshsent++;	else if (type == ESIS_ISH) 		esis_stat.es_ishsent++;	else {		printf("esis_shoutput: bad pdu type\n");		return;	}	IFDEBUG(D_ESISOUTPUT)		int	i;		printf("esis_shoutput: ifp x%x (%s%d), %s, ht %d, to: [%d] ",			ifp, ifp->if_name, ifp->if_unit, type == ESIS_ESH ? "esh" : "ish",			ht, sn_len);		for (i=0; i<sn_len; i++)			printf("%x%c", *(sn_addr+i), i < (sn_len-1) ? ':' : ' ');		printf("\n");	ENDDEBUG	if ((m0 = m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL) {		esis_stat.es_nomem++;		return;	}	bzero(mtod(m, caddr_t), MHLEN);	pdu = mtod(m, struct esis_fixed *);	naddrp = cp = (caddr_t)(pdu + 1);	len = sizeof(struct esis_fixed);	/*	 *	Build fixed part of header	 */	pdu->esis_proto_id = ISO9542_ESIS;	pdu->esis_vers = ESIS_VERSION;	pdu->esis_type = type;	HTOC(pdu->esis_ht_msb, pdu->esis_ht_lsb, ht);	if (type == ESIS_ESH) {		cp++;		len++;	}	m->m_len = len;	if (isoa) {		/*		 * Here we are responding to a clnp packet sent to an NSAP		 * that is ours which was sent to the MAC addr all_es's.		 * It is possible that we did not specifically advertise this		 * NSAP, even though it is ours, so we will respond		 * directly to the sender that we are here.  If we do have		 * multiple NSEL's we'll tack them on so he can compress them out.		 */		(void) esis_insert_addr(&cp, &len, isoa, m, 0);		naddr = 1;	}	for (ia = iso_ifaddr; ia; ia = ia->ia_next) {		int nsellen = (type == ESIS_ISH ? ia->ia_addr.siso_tlen : 0); 		int n = ia->ia_addr.siso_nlen;		register struct iso_ifaddr *ia2;		if (type == ESIS_ISH && naddr > 0)			break;		for (ia2 = iso_ifaddr; ia2 != ia; ia2 = ia2->ia_next)			if (Bcmp(ia->ia_addr.siso_data, ia2->ia_addr.siso_data, n) == 0)					break;		if (ia2 != ia)			continue;	/* Means we have previously copied this nsap */		if (isoa && Bcmp(ia->ia_addr.siso_data, isoa->isoa_genaddr, n) == 0) {			isoa = 0;			continue;	/* Ditto */		}		IFDEBUG(D_ESISOUTPUT)			printf("esis_shoutput: adding NSAP %s\n", 				clnp_iso_addrp(&ia->ia_addr.siso_addr));		ENDDEBUG		if (!esis_insert_addr(&cp, &len,							  &ia->ia_addr.siso_addr, m, nsellen)) {			EXTEND_PACKET(m, m0, cp);			(void) esis_insert_addr(&cp, &len, &ia->ia_addr.siso_addr, m,									nsellen);		}		naddr++;	}	if (type == ESIS_ESH)		*naddrp = naddr;	else {		/* add suggested es config timer option to ISH */		if (M_TRAILINGSPACE(m) < 4) {			printf("esis_shoutput: extending packet\n");			EXTEND_PACKET(m, m0, cp);		}		*cp++ = ESISOVAL_ESCT;		*cp++ = 2;		HTOC(*cp, *(cp+1), esis_esconfig_time);		len += 4;		m->m_len += 4;		IFDEBUG(D_ESISOUTPUT)			printf("m0 0x%x, m 0x%x, data 0x%x, len %d, cp 0x%x\n",			m0, m, m->m_data, m->m_len, cp);		ENDDEBUG	}	m0->m_pkthdr.len = len;	pdu->esis_hdr_len = len;	iso_gen_csum(m0, ESIS_CKSUM_OFF, (int)pdu->esis_hdr_len);	bzero((caddr_t)&siso, sizeof(siso));	siso.siso_family = AF_ISO;	siso.siso_data[0] = AFI_SNA;	siso.siso_nlen = sn_len + 1;	bcopy(sn_addr, siso.siso_data + 1, (unsigned)sn_len);	(ifp->if_output)(ifp, m0, (struct sockaddr *)&siso, 0);}/* * FUNCTION:		isis_input * * PURPOSE:			Process an incoming isis packet * * RETURNS:			nothing * * SIDE EFFECTS:	 * * NOTES:			 */isis_input(m0, shp)struct mbuf		*m0;		/* ptr to first mbuf of pkt */struct snpa_hdr	*shp;	/* subnetwork header */{	register int type;	register struct rawcb *rp, *first_rp = 0;	struct ifnet *ifp = shp->snh_ifp;	char workbuf[16];	struct mbuf *mm;	IFDEBUG(D_ISISINPUT)		int i;		printf("isis_input: pkt on ifp x%x (%s%d): from:", ifp, 			ifp->if_name, ifp->if_unit);		for (i=0; i<6; i++)			printf("%x%c", shp->snh_shost[i]&0xff, (i<5) ? ':' : ' ');		printf(" to:");		for (i=0; i<6; i++)			printf("%x%c", shp->snh_dhost[i]&0xff, (i<5) ? ':' : ' ');		printf("\n");	ENDDEBUG	esis_dl.sdl_alen = ifp->if_addrlen;	esis_dl.sdl_index = ifp->if_index;	bcopy(shp->snh_shost, (caddr_t)esis_dl.sdl_data, esis_dl.sdl_alen);	for (rp = esis_pcb.rcb_next; rp != &esis_pcb; rp = rp->rcb_next) {		if (first_rp == 0) {			first_rp = rp;			continue;		}		if (mm = m_copy(m0, 0, M_COPYALL)) { /*can't block at interrupt level */			if (sbappendaddr(&rp->rcb_socket->so_rcv,							  &esis_dl, mm, (struct mbuf *)0) != 0) {				sorwakeup(rp->rcb_socket);			 } else {				IFDEBUG(D_ISISINPUT)					printf("Error in sbappenaddr, mm = 0x%x\n", mm);				ENDDEBUG				m_freem(mm);			}		}	}	if (first_rp && sbappendaddr(&first_rp->rcb_socket->so_rcv,							  &esis_dl, m0, (struct mbuf *)0) != 0) {		sorwakeup(first_rp->rcb_socket);		return;	}	m_freem(m0);}isis_output(sdl, m)register struct sockaddr_dl	*sdl;struct mbuf *m;{	register struct ifnet *ifp;	struct ifaddr *ifa, *ifa_ifwithnet();	struct sockaddr_iso siso;	int error = 0;	unsigned sn_len;	ifa = ifa_ifwithnet((struct sockaddr *)sdl);	/* get ifp from sdl */	if (ifa == 0) {		IFDEBUG(D_ISISOUTPUT)			printf("isis_output: interface not found\n");		ENDDEBUG		error = EINVAL;		goto release;	}	ifp = ifa->ifa_ifp;	sn_len = sdl->sdl_alen;	IFDEBUG(D_ISISOUTPUT)		u_char *cp = (u_char *)LLADDR(sdl), *cplim = cp + sn_len;		printf("isis_output: ifp 0x%x (%s%d), to: ",			ifp, ifp->if_name, ifp->if_unit);		while (cp < cplim) {			printf("%x", *cp++);			printf("%c", (cp < cplim) ? ':' : ' ');		}		printf("\n");	ENDDEBUG	bzero((caddr_t)&siso, sizeof(siso));	siso.siso_family = AF_ISO; /* This convention may be useful for X.25 */	siso.siso_data[0] = AFI_SNA;	siso.siso_nlen = sn_len + 1;	bcopy(LLADDR(sdl), siso.siso_data + 1, sn_len);	error = (ifp->if_output)(ifp, m, (struct sockaddr *)&siso, 0);	if (error) {		IFDEBUG(D_ISISOUTPUT)			printf("isis_output: error from ether_output is %d\n", error);		ENDDEBUG	}	return (error);release:	if (m != NULL)		m_freem(m);	return(error);}/* * FUNCTION:		esis_ctlinput * * PURPOSE:			Handle the PRC_IFDOWN transition * * RETURNS:			nothing * * SIDE EFFECTS:	 * * NOTES:			Calls snpac_flush for interface specified. *					The loop through iso_ifaddr is stupid because *					back in if_down, we knew the ifp... */esis_ctlinput(req, siso)int						req;		/* request: we handle only PRC_IFDOWN */struct sockaddr_iso		*siso;		/* address of ifp */{	register struct iso_ifaddr *ia;	/* scan through interface addresses */	if (req == PRC_IFDOWN)		for (ia = iso_ifaddr; ia; ia = ia->ia_next) {			if (iso_addrmatch(IA_SIS(ia), siso))				snpac_flushifp(ia->ia_ifp);		}}#endif	/* ISO */

⌨️ 快捷键说明

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