📄 lat_hic.c
字号:
#ifndef lintstatic char *sccsid = "@(#)lat_hic.c 4.3 7/28/88";#endif/************************************************************************ * * * Copyright (c) 1988 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * 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. * * * ************************************************************************//************************************************************************ * Modification History * * * * Chung Wong - 1/7/88 First version. * * Subroutines to provide transparent host initiated * * connection, with algorithm similar to the handling of * * ioctls LIOCINI, LIOCSOL, LIOCRES and LIOCCMD. * * Provision for LAT master. * * * ************************************************************************//* lat_hic.c 0.0 12/11/84 */#include "../h/param.h"#include "../h/systm.h"#include "../h/mbuf.h"#include "../h/protosw.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/errno.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/file.h"#include "../h/gnode.h"#include "../h/proc.h"#include "../net/if.h"#include "../net/netisr.h"#include "../netinet/in.h"#include "../netinet/if_ether.h"#include "../lat/lat.h"#include "../lat/lat_protocol.h"#include "../lat/lat_var.h"#include "../h/ioctl.h"#include "../h/tty.h"extern struct socket *lat_traceso;extern struct sclass *sclass[];extern struct sclass class1;extern struct ecb statable[];extern u_short reqid;extern int wakeup();extern caddr_t buildvchdr();extern struct lat_vc *newvc(), *findvc(); extern struct lat_vc *vc[]; extern struct lat_slot sl[];extern struct tty lata[];extern struct ecb statable[];extern struct sclass *sclass[];extern struct vc_start startvc;extern u_char slotsinuse;extern struct lat_counters latctrs;extern int nLAT1;extern struct hic_entity lat_obj[];struct mbuf *lat_hicres();/* * LAT host-initiated connection routines. */ /* * l a t _ h i c i n i * * Process initialization for LAT host-initiated connection * * Returns: 0 if success * error code if not * * Inputs: * paths = Pointer to parameters (subj port, obj name/port) * (in format: /dev/ttyxx:server_name:server_port) * pathlen = length of path name for subject port * unit = index to "statable" (= minor device number) * cmdbyte = LIOCINI command byte */lat_hicini(paths,pathlen,unit,cmdbyte)char *paths;int pathlen,unit;u_char cmdbyte;{ struct hic_entity *lptr = &lat_obj[unit]; struct ecb *ecbp = &statable[unit]; int i; /* return error if device busy if ((ecbp->ecb_inuse & ECB_INUSE) || (lata[unit].t_addr)) return(EBUSY); */ lptr->status &= ~(HIC | MHIC); if (cmdbyte != '\001') return (0); /* * if no objects specified, return */ if (paths[pathlen-1] != ':') return(0); /* * save subject port name and length */ paths[pathlen-1] = '\0'; if ((lptr->subj_portlen = pathlen - 1) > MAXNAM) return(EADDRNOTAVAIL); bcopy(paths, lptr->subj_port, pathlen); paths[pathlen-1] = ':'; lptr->status |= SUBJPORT; /* * save object name */ paths += pathlen; if ((pathlen = lat_pathlen(paths)) == 1) return(0); if (paths[pathlen-1] != ':') return(0); if ((lptr->obj_namelen = pathlen - 1) > MAXNAM) return(EADDRNOTAVAIL); bcopy(paths, lptr->obj_name, pathlen-1); lptr->obj_name[pathlen-1] = 0; lptr->status |= OBJNAME; /* * save object port */ paths += pathlen; if ((pathlen = lat_pathlen(paths)) == 1) return(0); if ((lptr->obj_portlen = pathlen - 1) > MAXNAM) return(EADDRNOTAVAIL); #ifdef LATMASTER if (*paths == '.') /* latmaster */ { char *hex, ch1, ch2; paths++; for (i=0; *paths!='.'; i++,paths++) { ch1 = *paths++; ch2 = *paths; if (ch1<='9') ch1 &= 0x0f; else ch1 = (ch1 & 0x07) + 9; if (ch2<='9') ch2 &= 0x0f; else ch2 = (ch2 & 0x07) + 9; lptr->obj_port[i] = (ch1 << 4) + ch2; } lptr->obj_port[i] = '\0'; lptr->obj_portlen = i; lptr->status |= HOSTMASTER; } else#endif { bcopy(paths, lptr->obj_port, pathlen-1); lptr->status |= OBJPORT; } ecbp->ecb_hostinit = LAT_HIC; return(0);} /* * l a t _ h i c o p e n * * Process latopen request in case of host initiated connection * * Returns: 0 if success * error code if not * * Inputs: * unit = index to "statable" (= minor[subj port]) */lat_hicopen(unit,tp)int unit;struct tty *tp;{ int s, err; u_short solid; struct hic_entity *h = &lat_obj[unit]; struct mbuf *m0,*m1; struct solicit_1 *solptr; struct response_1 *resptr; struct ecb *ecbp = &(statable[unit]); struct ifnet *ifp = ifnet; struct proc *pp = u.u_procp; /* * if defined as master, return */ if (h->status & HOSTMASTER) return(0); /* * check if host-initiated connection fully defined */ if (ecbp->ecb_hostinit != LAT_HIC) return(0); if (((h->status & HIC) != HIC)) return(EDESTADDRREQ); /* * LAT open should be exclusive, unless multiplexing added */ if (ecbp->ecb_inuse & ECB_INUSE) { if (ecbp->ecb_inuse & ECB_NONHIC) return (0); return(EBUSY); } if (tp->t_addr) return(EBUSY); /* * if lat not running, return error */ if (class1.scl_state != LST_RUNNING) return(ENOPROTOOPT); ecbp->ecb_inuse |= ECB_INUSE; s = splnet(); /* * For each network interface, build solicit msg * with object name, then wait for response. Send * command msg to the first server that responded. */ while (ifp) { if ((ifp->if_flags & (IFF_BROADCAST|IFF_DYNPROTO|IFF_UP)) == (IFF_BROADCAST|IFF_DYNPROTO|IFF_UP)) { if (!(m0 = m_get(M_DONTWAIT, MT_DATA))) { err = ENOBUFS; goto badret; } m0->m_len = sizeof(struct solicit_1); solptr = mtod(m0, struct solicit_1 *); solptr->sol1_dstnodelen = h->obj_namelen; bcopy(h->obj_name, solptr->sol1_dstnode, h->obj_namelen); class1.scl_solicit(m0, ifp); solid = *(u_short *)solptr->sol1_solid; sleep(solptr->sol1_solid, TTIPRI); /* * get response msg */ if (m1 = lat_hicres(solid)) goto gotres; } ifp = ifp->if_next; } err = EADDRNOTAVAIL;badret: ecbp->ecb_inuse &= ~ECB_INUSE; splx(s); return (err); gotres: /* * send command msg */ err = lat_hiccmd(h,ifp,m1,unit); if (!err) lata[unit].t_pgrp = pp->p_pgrp; splx(s); return (err); }/* * l a t _ h i c r e s * * Get response msg with matched id * * Returns: mbuf with the response msg * 0 if no match found * * Inputs: * solid = id in the solicit msg * */struct mbuf *lat_hicres(solid)u_short solid;{ struct mbuf *n, *prev; struct response_1 *res_que; n = class1.scl_rmsg.q_head; /* * Find response information structure in response * queue matching solicit ID of user structure */ while (n) { res_que = mtod(n, struct response_1 *); if ( solid == *(u_short *)res_que->rs1_solid ) { if (n == class1.scl_rmsg.q_head) { if ( (class1.scl_rmsg.q_head = n->m_act) == 0) class1.scl_rmsg.q_tail = 0; } else { if (n == class1.scl_rmsg.q_tail) { class1.scl_rmsg.q_tail = prev; prev->m_act = 0; } else prev->m_act = n->m_act; } return(n); } else { prev = n; n = n->m_act; } } /* while n */ /* * response mas not found */ return( (struct mbuf *) 0);}/* * l a t _ h i c c m d * * Send command msg to request a connection * * Returns: 0 if success * error code if not * * Inputs: * h = pointer to the hic_entity structure * ifp = pointer to the network interface structure * m1 = pointer to mbuf with response msg * unit = index to "statable" (= minor[subj port]) */lat_hiccmd(h,ifp,m1,unit)struct hic_entity *h;struct ifnet *ifp;struct mbuf *m1;int unit;{ caddr_t commsg, dptr; u_char u_len; struct mbuf *m0, *cm; struct response_1 *resptr = mtod(m1,struct response_1 *); struct lat_cmd *commsgp; struct lataddr objaddr; struct ecb *ecbp = &(statable[unit]); /* * Copy Ethernet address of object node. */ bcopy((caddr_t)resptr->rs1_srcnode,(caddr_t)objaddr.lat_addr,6); objaddr.lat_family = AF_LAT; m_freem(m1); m0 = m_get(M_DONTWAIT,MT_DATA); commsgp = mtod(m0,struct lat_cmd *); /* * Build command message header. */ commsgp->lcm_type = MSG_CMD << 2; commsgp->lcm_protofmt = 0; commsgp->lcm_Hver = commsgp->lcm_Cver = LAT_VER; commsgp->lcm_Lver = LAT_VER_LOW; commsgp->lcm_eco = LAT_ECO; *(u_short *)commsgp->lcm_framesize = LAT_FRAMESIZE; *(u_short *)commsgp->lcm_reqid = reqid; *(u_short *)commsgp->lcm_entryid = (u_short)0; /* * set up command type and command modifier */ if (lata[unit].t_state & TS_ONDELAY) { /* for no delay, get non-queue service */ commsgp->lcm_cmdtype = 1; commsgp->lcm_cmdmod = 0; } else { /* queue service, with periodic return status */ commsgp->lcm_cmdtype = 2; commsgp->lcm_cmdmod = 1; } commsg = (caddr_t)commsgp; commsg += sizeof(struct lat_cmd); /* * object node name */ u_len = h->obj_namelen; *commsg++ = (char)h->obj_namelen; bcopy(h->obj_name,commsg,(int)u_len); commsg += u_len; /* * Add source node group identifier list, node name * directly from class1.scl_dmsg */ dptr = mtod(class1.scl_dmsg,caddr_t); dptr = (caddr_t)dptr + sizeof(struct direct_1); u_len = *commsg++ = *dptr++ ; (void)bcopy((caddr_t)dptr,commsg,(int)u_len); dptr += u_len, commsg += u_len; u_len = *commsg++ = *dptr++; (void)bcopy((caddr_t)dptr,commsg,(int)u_len); commsg += u_len; /* * subject port */ u_len = h->subj_portlen; *commsg++ = u_len; bcopy(h->subj_port, commsg, (int)u_len); commsg += u_len; /* * subject description =0, object service = 0 */ *commsg++ = 0; *commsg++ = 0; /* * object port */ u_len = h->obj_portlen; *commsg++ = u_len; bcopy(h->obj_port, commsg, (int)u_len); commsg += u_len; /* * null termination */ *commsg++ = 0; m0->m_len = (short)(commsg - (caddr_t)commsgp); ecbp->ecb_cmdmsg = m0; ecbp->ecb_reqid = *(u_short *)commsgp->lcm_reqid; ecbp->ecb_if = ifp; bcopy((caddr_t)objaddr.lat_addr, (caddr_t)(ecbp->ecb_addr.lat_addr),6); ecbp->ecb_addr.lat_family = AF_LAT; ecbp->ecb_statrecd = 0; /* * invoke network interface */ if (lat_traceso) ltt_trace(0,0,m0,objaddr.lat_addr); if (cm = m_copy(m0,0,M_COPYALL)) (*ifp->if_output)(ifp,cm,&objaddr); /* * Increment reqid, which must not be 0. */ reqid = ( (reqid == 0xffff) ? 1 : reqid + 1); return(0);} /* * l a t _ p a t h l e n *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -