📄 dli_subr.c
字号:
#ifndef lintstatic char *sccsid = "@(#)dli_subr.c 4.4 (DECnet-ULTRIX) 4/30/91";#endif/* * Program dli_subr.c, Module DLI * * Copyright (C) 1985, 1988 by * Digital Equipment Corporation, Maynard, Mass. * * This software is furnished under a license and may be used and copied * only in accordance with the terms of such license and with the * inclusion of the above copyright notice. This software or any other * copies thereof may not be provided or otherwise made available to any * other person. No title to and ownership of the software is hereby * transferred. * * The information in this software is subject to change without notice * and should not be construed as a commitment by Digital Equipment * Corporation. * * Digital assumes no responsibility for the use or reliability of its * software on equipment which is not supplied by Digital. * * * Networks & Communications Software Engineering * * IDENT HISTORY: * * 1.00 22-May-1986 * DECnet-ULTRIX V2.0 * * 2.01 18-Mar-1988 * DECnet-ULTRIX V2.4 * - Allowed use of reserved bit in individual and group SAPs * * 29-Apr-1991 Matt Thomas * staticly allocate m_ar array. Fix gsap to seach all 128 isaps. */#include "../../h/param.h"#include "../../h/systm.h"#include "../../h/mbuf.h"#include "../../h/socket.h"#include "../../h/socketvar.h"#include "../../h/protosw.h"#include "../../h/errno.h"#include "../../h/smp_lock.h"#include "../../h/cpudata.h"#include "../../h/user.h"#include "../../h/buf.h"#include "../../h/conf.h"#include "../../h/proc.h"#include "../../net/net/if.h"#include "../../net/net/if_to_proto.h"#include "../../net/netinet/in.h"#include "../../net/netinet/if_ether.h"#include "../../net/netdnet/dli_var.h"extern struct lock_t lk_dli;extern struct if_isapt if_isapt[];extern struct protosw *iftype_to_proto(), *iffamily_to_proto();extern int xti_debug;u_int dlidebug = 0;#define printd if(dlidebug)printf/* * initialize the system data structure * for 802.3 support. * * Note: Since this is part of DLI init at boot time, * all necessary locks taken out before this * routine is called. */osi_802init(ifp)struct ifnet *ifp;{ static int k = 0; if(k >= MAX_BROADCSTDEV) { return(-1); } bzero(&if_isapt[k], sizeof(struct if_isapt)); if_isapt[k++].ifp = ifp; return(NULL);}/* * enable an isap in the system wide table * * Note: DLI line table entry and socke locks * taken out before this routine called. */osi_ena_802isap(ifp, so, socket)struct ifnet *ifp;struct sockaddr_802 *so;struct socket *socket;{ int i, n, byte, error; u_char bit; if((so->eh_802.ssap & VSAP) || (so->eh_802.ssap >= 255) ) return(EINVAL); n = so->eh_802.ssap>>VSAP; /* throw out low bit */ byte = n>>3; /* byte in table = sap / 8 */ bit = 1<<(n%8); /* bit to set/clear = sap mod 8 */ smp_lock(&lk_dli, LK_RETRY); for(i = 0; i < MAX_BROADCSTDEV; i++) { if(if_isapt[i].ifp != ifp) continue; if(if_isapt[i].so[n] != 0) { smp_unlock(&lk_dli); return(EADDRINUSE); } if(so->svc == TYPE1) if_isapt[i].svc[byte] |= bit; /* set class 1 svc */ else if_isapt[i].svc[byte] &= ~bit; /* clear for user svc */ if_isapt[i].so[n] = socket; smp_unlock(&lk_dli); return(NULL); } smp_unlock(&lk_dli); return(ENOTFND);}/* * disable an isap in the system wide table * and any gsaps that this isap has enabled * * Note: DLI line table entry and socke locks * taken out before this routine called. */osi_dis_802isap(ifp, sap, sop)struct ifnet *ifp;u_char sap;struct socket *sop;{ int error, j, i, byte, bit, vsap; if( (sap & VSAP) || (sap >= 255) ) return(EINVAL); vsap = sap >> VSAP; byte = vsap/8; bit = 1 << vsap%8; smp_lock(&lk_dli, LK_RETRY); for(i = 0; i < MAX_BROADCSTDEV; i++) { if(if_isapt[i].ifp != ifp) continue; if(if_isapt[i].so[vsap] == 0) { smp_unlock(&lk_dli); return(EINVAL); } if(if_isapt[i].so[vsap] != sop) { smp_unlock(&lk_dli); return(EINVAL); } if_isapt[i].so[vsap] = NULL; /* look for and disable any gsaps this isap has enabled */ for(j = 0; j < NISAPS; j++) { if(if_isapt[i].gsap[j][byte] & bit) if(error = osi_dis_802gsap(ifp, ((j<<VSAP)|1), sap)) { smp_unlock(&lk_dli); return(error); } } smp_unlock(&lk_dli); return(NULL); } smp_unlock(&lk_dli); return(ENOTFND);}/* * enable gsap in the system wide table * * Note: DLI line table entry and socket locks * taken out before this routine called. */osi_ena_802gsap(ifp, gsap, sap)struct ifnet *ifp;int gsap, sap;{ int i, byte, bit; if( (sap >= 255) || (sap & VSAP)) return(EINVAL); if( (gsap <= NULL) || !(gsap & VSAP) || (gsap > 255) ) return(EINVAL); byte = (sap >> VSAP) / 8; bit = (sap >> VSAP) % 8; smp_lock(&lk_dli, LK_RETRY); for(i = 0; i < MAX_BROADCSTDEV; i++) { if(if_isapt[i].ifp != ifp) continue; if_isapt[i].gsap[gsap>>VSAP][byte] |= 1 << bit; smp_unlock(&lk_dli); return(NULL); } smp_unlock(&lk_dli); return(ENOTFND);}/* * disable gsap in system wide table * * Note: DLI line table entry and socke locks * taken out before this routine called. */osi_dis_802gsap(ifp, gsap, sap)struct ifnet *ifp;int gsap, sap;{ int i, byte, bit; u_char lk_dli_asserted_locally = 0; if( (sap >= 255) || (sap & VSAP)) return(EINVAL); if( (gsap <= NULL) || !(gsap & 1) || (gsap > 255) ) return(EINVAL); byte = (sap >> VSAP) / 8; bit = (sap >> VSAP) % 8; if ( smp_owner(&lk_dli) == LK_FALSE ) { smp_lock(&lk_dli, LK_RETRY); lk_dli_asserted_locally = 1; } for(i = 0; i < MAX_BROADCSTDEV; i++) { if(if_isapt[i].ifp != ifp) continue; if_isapt[i].gsap[gsap>>VSAP][byte] &= ~(1<< bit); if ( lk_dli_asserted_locally ) smp_unlock(&lk_dli); return(NULL); } if ( lk_dli_asserted_locally ) smp_unlock(&lk_dli); return(ENOTFND);}/* * test if an isap has this gsap enabled in system wide table * * Note: DLI line table entry and socket locks * taken out before this routine called. */osi_tst_802gsap(ifp, gsap, sap)struct ifnet *ifp;int gsap, sap;{ int i, byte, bit; if( (sap >= 255) || (sap & VSAP)) return(EINVAL); if( (gsap <= 0) || !(gsap & 1) || (gsap > 255) ) return(EINVAL); byte = (sap >> VSAP) / 8; bit = (sap >> VSAP) % 8; smp_lock(&lk_dli, LK_RETRY); for(i = 0; i < MAX_BROADCSTDEV; i++) { if(if_isapt[i].ifp != ifp) continue; if(if_isapt[i].gsap[gsap>>VSAP][byte] & (1<< bit)) { smp_unlock(&lk_dli); return(1); } else { smp_unlock(&lk_dli); return(NULL); } } smp_unlock(&lk_dli); return(ENOTFND);}/* * enable an 802.3 protocol (5 byte field) * for someone using the snap sap * * Note: DLI line table entry lock * taken out before this routine called. * No socket locks must be asserted! */osi_ena_802pi(so_802, ifp, ue)register struct sockaddr_802 *so_802;struct ifnet *ifp;struct dli_line *ue;{ u_char dmy_pi[5]; extern struct dli_line dli_ltable[]; register int i, error; register struct sockaddr_802 *search_eaddr; u_char flags = so_802->ioctl; bzero(dmy_pi, 5); if(bcmp(so_802->eh_802.osi_pi, dmy_pi, 5) == 0) return(EINVAL); /* * Only one control flag should be set. */ switch (flags) { case DLI_EXCLUSIVE: case DLI_NORMAL: case DLI_DEFAULT: break; default: return(EINVAL); break; } /* * Make sure address structure is unique per device. */ for ( i = 0; i < dli_maxline; i++ ) { if ( &dli_ltable[i] == ue ) continue; smp_lock(&dli_ltable[i].dli_lk, LK_RETRY); if (dli_ltable[i].dli_lineid.dli_substructype != DLI_802 || dli_ltable[i].dli_so == NULL || ifp != dli_ltable[i].dli_if ) { smp_unlock(&dli_ltable[i].dli_lk); continue; } search_eaddr = &dli_ltable[i].dli_lineid.choose_addr.dli_802addr; error = NULL; switch (search_eaddr->ioctl) { case NULL: break; case DLI_EXCLUSIVE: error = (bcmp(search_eaddr->eh_802.osi_pi, so_802->eh_802.osi_pi, 5) == NULL) ? EADDRINUSE : NULL; break; case DLI_NORMAL: switch (flags) { case DLI_EXCLUSIVE: error = (bcmp(search_eaddr->eh_802.osi_pi, so_802->eh_802.osi_pi, 5) == NULL) ? EADDRINUSE : NULL; break; case DLI_NORMAL: if(bcmp(search_eaddr->eh_802.osi_pi, so_802->eh_802.osi_pi, 5) == NULL) { error = match_targets(search_eaddr->eh_802.dst, so_802->eh_802.dst); } else { error = NULL; } break; default: break; } break; case DLI_DEFAULT: switch (flags) { case DLI_EXCLUSIVE: case DLI_DEFAULT: error = (bcmp(search_eaddr->eh_802.osi_pi, so_802->eh_802.osi_pi, 5) == NULL) ? EADDRINUSE : NULL; break; default: break; } break; default: panic( "dli_bind: osi_ena_802pi:" ); break; } smp_unlock(&dli_ltable[i].dli_lk); if (error != NULL) { return(error); } } return(NULL);}/* * build an 802 header for transmission */struct mbuf *osi_buildhdr(dst_addr)struct sockaddr_dl *dst_addr;{ struct mbuf *temp, *m = NULL; u_char *cp; MGET(m, M_DONTWAIT, MT_DATA); if ( m ) { cp = mtod(m,u_char *); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.dsap); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.ssap); if((dst_addr->choose_addr.dli_802addr.eh_802.ctl.U_fmt & 3) == 3) { PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.ctl.U_fmt); if(dst_addr->choose_addr.dli_802addr.eh_802.ssap == SNAP_SAP) { PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.osi_pi[0]); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.osi_pi[1]); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.osi_pi[2]); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.osi_pi[3]); PUT8B(cp, dst_addr->choose_addr.dli_802addr.eh_802.osi_pi[4]); m->m_len = 8; } else m->m_len = 3; } else { PUT16B(cp, dst_addr->choose_addr.dli_802addr.eh_802.ctl.I_S_fmt); m->m_len = 4; } } return(m);}/* * handle 802 incoming packets * otherwise drop packet * otherwise drop packet * pull any header information from the 2nd mbuf to * guarantee that only data is there * * input packet as a chain of mbufs, first mbuf has garbage * 2nd mbuf will have the rest of the 802 header * return nothing */osi_802input(m, rcv)struct mbuf *m;struct dli_recv *rcv;{ u_char *cp, bit; int len, cnt, byte, i, j, k; struct osi_802hdr *eh; struct ifnet *ifp; /* * This structure is protected by the dliintrq queue ownership code * in dliintr(). That code assures that only one cpu at a time will * process input packets. */ static struct { /* used for gsaps to make copies of packet */ int sap; struct mbuf *m; struct socket *so; } m_ar[NISAPS]; register struct socket *so = NULL; u_char svc; struct dli_line *ue, *dli_getlte_notrust(); eh = &rcv->rcv_hdr.osi_header;#ifdef IFT_FDDI eh->len = m_length(m->m_next);#else len = m_length(m->m_next); if ( len != eh->len && len != DLI_MINPKT ) { printd("osi_802input: invalid length, indicated = %d, actual = %d\n", eh->len, len); goto dropit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -