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

📄 llc_subr.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * Copyright (C) Dirk Husemann, Computer Science Department IV,  * 		 University of Erlangen-Nuremberg, Germany, 1990, 1991, 1992 * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. *  * This code is derived from software contributed to Berkeley by * Dirk Husemann and the Computer Science Department (IV) of * the University of Erlangen-Nuremberg, Germany. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)llc_subr.c	8.1 (Berkeley) 6/10/93 */#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/domain.h>#include <sys/socket.h>#include <sys/protosw.h>#include <sys/socketvar.h>#include <sys/errno.h>#include <sys/time.h>#include <sys/kernel.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_llc.h>#include <net/route.h>#include <netccitt/dll.h>#include <netccitt/llc_var.h>/* * Frame names for diagnostic messages */char *frame_names[] = { "INFO", "RR", "RNR", "REJ", "DM", "SABME", "DISC",	"UA", "FRMR", "UI", "XID", "TEST", "ILLEGAL", "TIMER", "N2xT1"};/* * Trace level */int llc_tracelevel = LLCTR_URGENT;/* * Values for accessing various bitfields */struct bitslice llc_bitslice[] = {/*	  mask, shift value */	{ 0x1,  0x0 },	{ 0xfe, 0x1 },	{ 0x3,  0x0 },	{ 0xc,  0x2 },	{ 0x10, 0x4 },	{ 0xe0, 0x5 },	{ 0x1f, 0x0 }};/* * We keep the link control blocks on a doubly linked list -  * primarily for checking in llc_time()  */struct llccb_q llccb_q = { &llccb_q, &llccb_q };/* * Flag for signalling wether route tree for AF_LINK has been * initialized yet. */int af_link_rts_init_done = 0; /* * Functions dealing with struct sockaddr_dl *//* Compare sdl_a w/ sdl_b */sdl_cmp(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b){	if (LLADDRLEN(sdl_a) != LLADDRLEN(sdl_b))		return(1);	return(bcmp((caddr_t) sdl_a->sdl_data, (caddr_t) sdl_b->sdl_data,		    LLADDRLEN(sdl_a)));}/* Copy sdl_f to sdl_t */sdl_copy(struct sockaddr_dl *sdl_f, struct sockaddr_dl *sdl_t){	bcopy((caddr_t) sdl_f, (caddr_t) sdl_t, sdl_f->sdl_len);}/* Swap sdl_a w/ sdl_b */sdl_swapaddr(struct sockaddr_dl *sdl_a, struct sockaddr_dl *sdl_b){	struct sockaddr_dl sdl_tmp;	sdl_copy(sdl_a, &sdl_tmp); 	sdl_copy(sdl_b, sdl_a); 	sdl_copy(&sdl_tmp, sdl_b);}/* Fetch the sdl of the associated if */struct sockaddr_dl * sdl_getaddrif(struct ifnet *ifp){	register struct ifaddr *ifa;	for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 			if (ifa->ifa_addr->sa_family == AF_LINK ) 					return((struct sockaddr_dl *)(ifa->ifa_addr));	return((struct sockaddr_dl *)0);}/* Check addr of interface with the one given */sdl_checkaddrif(struct ifnet *ifp, struct sockaddr_dl *sdl_c){	register struct ifaddr *ifa;	for(ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 			if ((ifa->ifa_addr->sa_family == AF_LINK ) && 	 		    !sdl_cmp((struct sockaddr_dl *)(ifa->ifa_addr), sdl_c))			return(1);		return(0);}/* Build an sdl from MAC addr, DLSAP addr, and interface */sdl_setaddrif(struct ifnet *ifp, u_char *mac_addr, u_char dlsap_addr, 	      u_char mac_len, struct sockaddr_dl *sdl_to){	register struct sockaddr_dl *sdl_tmp;	if ((sdl_tmp = sdl_getaddrif(ifp)) ) { 			sdl_copy(sdl_tmp, sdl_to); 			bcopy((caddr_t) mac_addr, (caddr_t) LLADDR(sdl_to), mac_len);		*(LLADDR(sdl_to)+mac_len) = dlsap_addr;		sdl_to->sdl_alen = mac_len+1; 			return(1); 	} else return(0);}/* Fill out the sdl header aggregate */sdl_sethdrif(struct ifnet *ifp, u_char *mac_src, u_char dlsap_src, u_char *mac_dst,	     u_char dlsap_dst, u_char mac_len, struct sdl_hdr *sdlhdr_to){	if ( !sdl_setaddrif(ifp, mac_src, dlsap_src, mac_len,			     &sdlhdr_to->sdlhdr_src) ||	     !sdl_setaddrif(ifp, mac_dst, dlsap_dst, mac_len,			     &sdlhdr_to->sdlhdr_dst) )		return(0);	else return(1);}static struct sockaddr_dl sap_saddr; static struct sockaddr_dl sap_sgate = {	sizeof(struct sockaddr_dl), /* _len */ 	AF_LINK                     /* _af */};/* * Set sapinfo for SAP address, llcconfig, af, and interface */struct npaidbentry *llc_setsapinfo(struct ifnet *ifp, u_char af, u_char sap, struct dllconfig *llconf){	struct protosw *pp; 	struct sockaddr_dl *ifdl_addr; 	struct rtentry *sirt = (struct rtentry *)0; 	struct npaidbentry *sapinfo; 	u_char saploc; 	int size = sizeof(struct npaidbentry);	USES_AF_LINK_RTS;	/* 	 * We rely/assume that only STREAM protocols will make use of 	 * connection oriented LLC2. If this will one day not be the 	 * case this will obviously fail. 	 */ 	pp = pffindtype (af, SOCK_STREAM); 	if (pp == 0 || pp->pr_input == 0 || pp->pr_ctlinput == 0) { 			printf("network	level protosw error"); 			return 0; 	}	/*	 * We need a way to jot down the LLC2 configuration for	 * a certain LSAP address. To do this we enter 	 * a "route" for the SAP.	 */	ifdl_addr = sdl_getaddrif(ifp);	sdl_copy(ifdl_addr, &sap_saddr); 	sdl_copy(ifdl_addr, &sap_sgate);	saploc = LLSAPLOC(&sap_saddr, ifp); 	sap_saddr.sdl_data[saploc] = sap;	sap_saddr.sdl_alen++;	/* now enter it */ 	rtrequest(RTM_ADD, (struct sockaddr *)&sap_saddr,			(struct sockaddr *)&sap_sgate, 0, 0, &sirt); 	if (sirt == 0) 			return 0;	/* Plug in config information in rt->rt_llinfo */	sirt->rt_llinfo = malloc(size , M_PCB, M_WAITOK); 	sapinfo = (struct npaidbentry *) sirt->rt_llinfo; 	if (sapinfo) { 			bzero ((caddr_t)sapinfo, size); 			/* 	 		 * For the time being we support LLC CLASS II here 	 		 * only 	 		 */ 			sapinfo->si_class = LLC_CLASS_II; 			sapinfo->si_window = llconf->dllcfg_window;		sapinfo->si_trace = llconf->dllcfg_trace; 			if (sapinfo->si_trace)			llc_tracelevel--;		else llc_tracelevel++;		sapinfo->si_input = pp->pr_input; 			sapinfo->si_ctlinput = (caddr_t (*)())pp->pr_ctlinput;		return (sapinfo);	}	return 0;}/* * Get sapinfo for SAP address and interface  */struct npaidbentry *llc_getsapinfo(u_char sap, struct ifnet *ifp){	struct sockaddr_dl *ifdl_addr; 	struct sockaddr_dl si_addr; 	struct rtentry *sirt; 	u_char saploc;	USES_AF_LINK_RTS;	ifdl_addr = sdl_getaddrif(ifp); 	sdl_copy(ifdl_addr, &si_addr); 	saploc = LLSAPLOC(&si_addr, ifp); 	si_addr.sdl_data[saploc] = sap;	si_addr.sdl_alen++;	if ((sirt = rtalloc1((struct sockaddr *)&si_addr, 0))) 			sirt->rt_refcnt--; 	else return(0);	return((struct npaidbentry *)sirt->rt_llinfo);}/* * llc_seq2slot() --- We only allocate enough memory to hold the window. This * introduces the necessity to keep track of two ``pointers'' * *        o llcl_freeslot     the next free slot to be used *                            this one advances modulo llcl_window *        o llcl_projvs       the V(S) associated with the next frame *                            to be set via llcl_freeslot *                            this one advances modulo LLC_MAX_SEQUENCE * * A new frame is inserted at llcl_output_buffers[llcl_freeslot], after * which both llcl_freeslot and llcl_projvs are incremented. * * The slot sl(sn) for any given sequence number sn is given by * *        sl(sn) = (llcl_freeslot + llcl_window - 1 - (llcl_projvs + *                  LLC_MAX_SEQUENCE- sn) % LLC_MAX_SEQUENCE) %  *                  llcl_window  * * i.e. we first calculate the number of frames we need to ``go back'' * from the current one (really the next one, but that doesn't matter as * llcl_projvs is likewise of by plus one) and subtract that from the * pointer to the most recently taken frame (llcl_freeslot - 1). */shortllc_seq2slot(struct llc_linkcb *linkp, short seqn){	register sn = 0;	sn = (linkp->llcl_freeslot + linkp->llcl_window - 	      (linkp->llcl_projvs + LLC_MAX_SEQUENCE - seqn) % 	      LLC_MAX_SEQUENCE) % linkp->llcl_window;	return sn;}/* * LLC2 link state handler * * There is in most cases one function per LLC2 state. The LLC2 standard * ISO 8802-2 allows in some cases for ambiguities, i.e. we have the choice * to do one thing or the other. Right now I have just chosen one but have also  * indicated the spot by "multiple possibilities". One could make the behavior  * in those cases configurable, allowing the superuser to enter a profile word * (32/64 bits, whatever is needed) that would suit her needs [I quite like  * that idea, perhaps I'll get around to it]. * * [Preceeding each state handler function is the description as taken from * ISO 8802-2, section 7.9.2.1] *//* * ADM --- The connection component is in the asynchronous disconnected mode. *         It can accept an SABME PDU from a remote LLC SSAP or, at the request *         of the service access point user, can initiate an SABME PDU *         transmission to a remote LLC DSAP, to establish a data link *         connection. It also responds to a DISC command PDU and to any *         command PDU with the P bit set to ``1''. */intllc_state_ADM(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,	      int cmdrsp, int pollfinal){	int action = 0;	switch(frame_kind + cmdrsp) {	case NL_CONNECT_REQUEST:		llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);		LLC_SETFLAG(linkp, P, pollfinal);		LLC_SETFLAG(linkp, S, 0);		linkp->llcl_retry = 0;		LLC_NEWSTATE(linkp, SETUP);		break;	case LLCFT_SABME + LLC_CMD:		/* 		 * ISO 8802-2, table 7-1, ADM state says to set		 * the P flag, yet this will cause an SABME [P] to be		 * answered with an UA only, not an UA [F], all		 * other `disconnected' states set the F flag, so ...		 */		LLC_SETFLAG(linkp, F, pollfinal);		LLC_NEWSTATE(linkp, CONN);		action = LLC_CONNECT_INDICATION;		break;	case LLCFT_DISC + LLC_CMD:		llc_send(linkp, LLCFT_DM, LLC_RSP, pollfinal);		break;	default:		if (cmdrsp == LLC_CMD && pollfinal == 1) 			llc_send(linkp, LLCFT_DM, LLC_RSP, 1);		/* remain in ADM state */	}	return action;}/* * CONN --- The local connection component has received an SABME PDU from a *          remote LLC SSAP, and it is waiting for the local user to accept or *          refuse the connection. */intllc_state_CONN(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,	       int cmdrsp, int pollfinal){	int action = 0;	switch(frame_kind + cmdrsp) {	case NL_CONNECT_RESPONSE:		llc_send(linkp, LLCFT_UA, LLC_RSP, LLC_GETFLAG(linkp, F));		LLC_RESETCOUNTER(linkp);		LLC_SETFLAG(linkp, P, 0);		LLC_SETFLAG(linkp, REMOTE_BUSY, 0);		LLC_NEWSTATE(linkp, NORMAL);		break;	case NL_DISCONNECT_REQUEST:		llc_send(linkp, LLCFT_DM, LLC_RSP, LLC_GETFLAG(linkp, F));		LLC_NEWSTATE(linkp, ADM);		break;	case LLCFT_SABME + LLC_CMD:		LLC_SETFLAG(linkp, F, pollfinal);		break;	case LLCFT_DM + LLC_RSP:		LLC_NEWSTATE(linkp, ADM);		action = LLC_DISCONNECT_INDICATION;		break;	/* all other frames effect nothing here */	}	return action;}/* * RESET_WAIT --- The local connection component is waiting for the local user *                 to indicate a RESET_REQUEST or a DISCONNECT_REQUEST.   */intllc_state_RESET_WAIT(struct llc_linkcb *linkp, struct llc *frame, int frame_kind,		     int cmdrsp, int pollfinal){	int action = 0;	switch(frame_kind + cmdrsp) {	case NL_RESET_REQUEST:		if (LLC_GETFLAG(linkp, S) == 0) {			llc_send(linkp, LLCFT_SABME, LLC_CMD, pollfinal);			LLC_SETFLAG(linkp, P, pollfinal);			LLC_START_ACK_TIMER(linkp);			linkp->llcl_retry = 0;			LLC_NEWSTATE(linkp, RESET);		} else {			llc_send(linkp, LLCFT_UA, LLC_RSP, 				      LLC_GETFLAG(linkp, F));			LLC_RESETCOUNTER(linkp);			LLC_SETFLAG(linkp, P, 0);			LLC_SETFLAG(linkp, REMOTE_BUSY, 0);			LLC_NEWSTATE(linkp, NORMAL);			action = LLC_RESET_CONFIRM;		}

⌨️ 快捷键说明

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