/****************************************************************************** * * (c) Copyright 1992, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. * ALL RIGHTS RESERVED * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT * NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL * OR ITS THIRD PARTY SUPPLIERS * * DIGITAL AND ITS THIRD PARTY SUPPLIERS, ASSUME NO RESPONSIBILITY FOR * THE USE OR INABILITY TO USE ANY OF ITS SOFTWARE . THIS SOFTWARE IS PROVIDED * "AS IS" WITHOUT WARRANTY OF ANY KIND, AND DIGITAL EXPRESSLY DISCLAIMS ALL * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Notice: Notwithstanding any other lease or license that may pertain to, * or accompany the delivery of, this computer software, the rights of the * Government regarding its use, reproduction and disclosure are as set * forth in Section 52.227-19 of the FARS Computer Software-Restricted * Rights clause. * * (c) Copyright 1992. Unpublished - all * rights reserved under the Copyright laws of the United States. * * RESTRICTED RIGHTS NOTICE: Use, duplication, or disclosure by the * Government is subject to the restrictions as set forth in subparagraph * (c)(1)(ii) of the Rights in Technical Data and Computer Software clause * at DFARS 52.227-7013. * * DIGITAL EQUIPMENT CORP. * 550 KING ST. * LITTLETON, MA * (508)486-5330 * * RESTRICTED RIGHTS LEGEND: This computer software is submitted with * "restricted rights." Use, duplication or disclosure is subject to the * restrictions as set forth in NASA FAR SUP 18-52.227-79 (April 1985) * "Commercial Computer Software- Restricted Rights (April 1985)." * * * DEC is a registered trademark of Digital Equipment Corporation * DIGITAL is a registered trademark of Digital Equipment Corporation * * DIGITAL distributes this software as a sample program for a remote * source to inter-operate with DECmcc Data Collector AM. Digital expects * no revenue from this program, and grants the rights to anyone who * has licenses for DECmcc to copy, distribute, or modify this program * at their risk. Digital retains the rights of authorship of the * program with its current functionality. It can not be resold without * the obtaining permission from Digital Equipment Corp. * Digital does not claim the rights of derivative works * which substantially alter the functionality of the original program. * Although this program works with the V1.2 release of DECmcc, Digital * makes no claims that it will perform any particular function, will * perform a similar function with another release of DECmcc, that * DECmcc future versions will interoperate with this sample, or that * a similar sample will be made available in any future releases. * The user of the sample is responsible to modify and test it adequately * for any desired functions that they desire. * * Access to this sample in no way implies a limit to Digital's ownership * of the Data Collector AM, any DECmcc software component, or DECmcc * as a whole. Nor does access to this sample imply any current or * future rights to use DECmcc. All rights to use DECmcc and/or any * of its componenents are detailed in the various licenses of those * components and are in no way abrogated by access to this sample. * ******************************************************************************/ /*********************************************************************** MODULE NAME: mcc_evc_api_dna_unix.c FACILITY: MCC -- Management Control Center ABSTRACT: The mcc_evc_dna_unix.c module contains code necessary to implement non-transparent Phase IV DECnet services on un*x operating systems. ENVIRONMENT: Ultrix Using the "C" programming language. AUTHOR: J.L. CREATION DATE: 24-oct-1991 MODIFICATION HISTORY: * Version Date Reviser Reason * -------- ----------- ------------- ---------------------------- * 1.31 Febr 1994 V.D Porting to OSF * T1.4.0 Sept-1994 F. Amrani Back porting from OSF to VMS/ULTRIX *************************************************************/ #include #include #include /* error numbers */ #if _MCC_OSIMPL_==_MCC__OS_OSF #include /* system data types */ #include /* socket definitions */ #else #include /* system data types */ #include /* socket definitions */ #endif /*__osf__*/ #include /* decnet socket definitions */ #include /* decnet database /usr/sys/net/netdnet */ #include #include #include #include #include "mcc_evc_api_def.h" /************************************************************************* * * ROUTINE: * * mcc_evc_dna_xlate_error * * FUNCTIONAL DESCRIPTION: * * * * * * * * INPUT: * * I_ultrix_error Longword Value containing Ultrix error code * * * MAJOR ALGORITHMS: * * * * * MODIFICATION HISTORY: * * V1.2-0 J L 24 Oct 1991 * Creation. * *************************************************************************/ static MCC_T_CVR mcc_evc_dna_xlate_error (MCC_T_Integer32 I_ultrix_error) { /* local variables */ MCC_T_CVR rs; rs = MCC_S_NORMAL; switch (I_ultrix_error) { case EACCES: /* Connect failed, Access control rejected */ rs = MCC_K_OP_NOT_ACCEPTED; break; case EADDRNOTAVAIL: /* Unrecognized node name */ rs = MCC_K_NO_SUCH_ENTITY; break; case ECONNREFUSED: /* Connect failed, Connection rejected by object */ rs = MCC_K_OP_NOT_ACCEPTED; break; case EHOSTDOWN: /* Connect failed, Local node is not on */ case ENETDOWN: /* Connect failed, Remote node shut down */ case EHOSTUNREACH: /* Connect failed, Node unreachable */ rs = MCC_K_CANNOT_COMMUNICATE; break; case ENOBUFS: /* Connect failed, Insufficient network resources */ case ENOSPC: /* Connect failed, Insufficient network resources */ rs = MCC_K_NO_RESOURCE_PROVIDER; break; case ETIMEDOUT: /* Connect failed, No response from object */ rs = MCC_K_INT_COMMUNICATION; break; case ETOOMANYREFS: /* Connect failed, Object too busy */ rs = MCC_K_NO_RESOURCE_ENTITY; break; case EBADF: /* Bad file number */ case EBUSY: /* Mount device busy */ case EMFILE: /* Too many open files */ case ENFILE: /* File table overflow */ case EDOM: /* Argument too large */ case EFAULT: /* Bad address */ case EMSGSIZE: /* Message too long */ case EOPNOTSUPP: /* Operation not supported */ case EINVAL: /* Connect failed, Invalid object name format */ case EINPROGRESS: /* Operation now in progress */ case EISCONN: /* The socket is already connected */ case EAFNOSUPPORT: /* Address family not supported by protocol family*/ case ESRCH: /* Connect failed, Unrecognized object */ case EPROTONOSUPPORT: /* Protocol not supported */ case ESOCKTNOSUPPORT: /* Socket type not supported */ case ENOPROTOOPT: /* Protocol not available */ default: rs = MCC_K_PROTOCOL_ERR; break; } return (rs); } /* End routine mcc_evc_dna_xlate_error */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_connect * * * MAJOR ALGORITHMS: * * Create a communication Socket. * Set socket optional data. * Issue a Connect request. * * * MODIFICATION HISTORY: * * V1.1-0 John Purretta 04 February 1991 * Creation. * *************************************************************************/ MCC_T_Integer32 mcc_evc_dna_connect (evc_t_cs *pI_destination, evc_t_handle *pO_assc_handle) { /* Local variables */ static MCC_T_UNSBYTE sink_name[] = {'M','C','C','_','E','V','C','_','S','I','N','K'}; MCC_T_Integer32 sock_d, sock_namelen, cnt_sent; MCC_T_Unsigned32 rs= MCC_S_NORMAL; struct sockaddr_dn sock_dnaddr; struct dn_naddr *p_dnaddr; struct nodeent *p_nodeent; struct evc_dna_iob *p_dna_iob; /* allocate memory for assoc_handle->p_iob */ p_dna_iob = (struct evc_dna_iob *)mcc_calloc(1, sizeof(struct evc_dna_iob)); if (p_dna_iob != NULL) { p_dna_iob->p_iosb = (struct evc_dna_iosb *)mcc_calloc(1, sizeof(struct evc_dna_iosb)); if (p_dna_iob->p_iosb != NULL) { p_dna_iob->iob_w_devchn = 0; p_dna_iob->iob_w_mbxchn = 0; p_dna_iob->p_iosb->iosb_w_iostat = 1; p_dna_iob->p_iosb->iosb_w_bytcnt = 0; p_dna_iob->p_iosb->iosb_l_info = 0; } else rs = MCC_S_MEM_ALLOC_FAILED; /* temporary */ } else rs = MCC_S_MEM_ALLOC_FAILED; if (rs == MCC_S_NORMAL) { sock_d = socket(AF_DECnet,SOCK_STREAM, 0); if (sock_d < 0) { perror("Create socket failed.\n"); rs = mcc_evc_dna_xlate_error(errno); } else { /* prepare a decnet socket address structure */ bzero((char*)&sock_dnaddr,sizeof(struct sockaddr_dn)); sock_dnaddr.sdn_family = AF_DECnet; sock_dnaddr.sdn_objnamel = sizeof(sink_name); /* <= 12 chars */ memcpy (sock_dnaddr.sdn_objname,sink_name, sizeof(sink_name)); if ( (p_dnaddr = dnet_addr( pI_destination->cs_string )) != 0) sock_dnaddr.sdn_add = *p_dnaddr; else { if ((p_nodeent =getnodebyname( (char*)pI_destination->cs_string)) != 0) { sock_dnaddr.sdn_add.a_len = p_nodeent->n_length; bcopy( p_nodeent->n_addr,sock_dnaddr.sdn_add.a_addr, p_nodeent->n_length ); } else /* node not recognized by address or name. */ rs = MCC_K_NO_SUCH_ENTITY; } } /* end of else */ } if (rs == MCC_S_NORMAL) { /* iniatiate the connect request to lncair */ if (connect(sock_d,(struct sockaddr*)&sock_dnaddr,sizeof(sock_dnaddr)) < 0) { perror("Connect failed.\n"); close (sock_d); rs = mcc_evc_dna_xlate_error(errno); } else { /* save sock_d in the association handle */ p_dna_iob->iob_w_devchn = (MCC_T_Integer16)sock_d; pO_assc_handle->net_io.p_iob = p_dna_iob; } } if (rs != MCC_S_NORMAL) { /* dealloc the iob and iosb */ if (p_dna_iob->p_iosb != NULL) { mcc_free(p_dna_iob->p_iosb); p_dna_iob->p_iosb = NULL ; } if (p_dna_iob != NULL) { mcc_free(p_dna_iob); p_dna_iob = NULL ; } pO_assc_handle->net_io.p_iob = NULL; /* null pointer */ } return (rs); } /* End routine mcc_evc_dna_connect */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_disconnect * * FUNCTIONAL DESCRIPTION: * * Retrieve sock. * Close sock. * Deallocate memory for assc_handle * * INPUT: * * * MAJOR ALGORITHMS: * * * * MODIFICATION HISTORY: * * V1.2-0 J L 24 OCt 1991 * Creation. * *************************************************************************/ MCC_T_Integer32 mcc_evc_dna_disconnect (evc_t_handle *pIO_assc_handle) { /* local variable s*/ MCC_T_Integer32 sock; /* Connection socket */ /* retrieve the sock info from the associate handle */ sock = (MCC_T_Integer32)pIO_assc_handle->net_io.p_iob->iob_w_devchn; if ( sock != 0 ) /* If socket exists */ { close ( sock ); /* disconnect the socket */ if (pIO_assc_handle->net_io.p_iob->p_iosb != NULL) mcc_free(pIO_assc_handle->net_io.p_iob->p_iosb); if (pIO_assc_handle->net_io.p_iob != NULL) mcc_free(pIO_assc_handle->net_io.p_iob); pIO_assc_handle->net_io.p_iob = NULL; /* null pointer */ } return (MCC_S_NORMAL); } /* End routine mcc_evc_dna_disconnect (Ultrix version) */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_send_msg * * FUNCTIONAL DESCRIPTION: * * * * * * * * INPUT: * * pI_msg Pointer to formatted message * * pI_iob Pointer to an I/O Block * * * MAJOR ALGORITHMS: * * * * * MODIFICATION HISTORY: * * V1.2-0 J. L 24 oct 1991 * Creation. * *************************************************************************/ MCC_T_Integer32 mcc_evc_dna_send_msg (struct dsc_descriptor *pI_msg, evc_t_handle *pIO_assc_handle) { /* local variables */ MCC_T_Integer32 bytes_sent = 0, sock = 0, /* Connection socket */ status = MCC_S_NORMAL; struct evc_dna_iob *p_dna_iob; /* retrieve the sock info from the associate handle */ sock = (int)pIO_assc_handle->net_io.p_iob->iob_w_devchn; #ifndef NOT_MCC TRY bytes_sent = write ( sock, (void*)pI_msg->dsc_a_pointer, (size_t)pI_msg->dsc_w_length ); CATCH (cma_e_alerted) { bytes_sent = -1 ; } ENDTRY #else bytes_sent = write ( sock, (void*)pI_msg->dsc_a_pointer, (size_t)pI_msg->dsc_w_length ); #endif if ( bytes_sent >= 0 ) { pIO_assc_handle->net_io.p_iob->p_iosb->iosb_w_bytcnt = (MCC_T_Integer16) bytes_sent; } else { close (sock); status = mcc_evc_dna_xlate_error(errno); } return ( status ); } /* End routine mcc_evc_dna_send_msg (Ultrix version) */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_connect_accept * * FUNCTIONAL DESCRIPTION: * * listen connection on original socket * accept the first new connection on this socket * and create a copy of the original socket to handle the connection * * INPUT: * * pI_iob Pointer to an I/O Block * * pI_opt Pointer to optional disconnect data * * * * * MODIFICATION HISTORY: * * V1.2-0 JL 14-sept-1991 * Creation. * *************************************************************************/ MCC_T_CVR mcc_evc_dna_connect_accept (struct MCC_R_DA_IOB *pIO_iob, struct dsc_descriptor *pI_ncb, struct dsc_descriptor *pI_opt) { /* local variables */ MCC_T_CVR mcc_status = MCC_S_NORMAL; struct sockaddr_dn acc_sock_addr; int evc_sock_d, read_sock_d = 0, asa_len = 0; MCC_T_Boolean alerted = MCC_K_FALSE; evc_sock_d = pIO_iob->iob_w_lnk; /* Copy stored socket from iob */ if ( evc_sock_d != 0 ) /* If socket exists */ { /* listen for connect request, backlog 1 for now */ if ((listen(evc_sock_d,1)) < 0) { perror("Listen failed.\n"); mcc_status = mcc_evc_dna_xlate_error(errno); } else { /* prepare accept socket address */ asa_len = sizeof(acc_sock_addr); bzero((char*)&acc_sock_addr, asa_len); /* initialize to 0 */ #ifndef NOT_MCC TRY read_sock_d = accept( evc_sock_d, (struct sockaddr *)&acc_sock_addr, &asa_len); CATCH (cma_e_alerted) { alerted = MCC_K_TRUE; } ENDTRY #else read_sock_d = accept( evc_sock_d, (struct sockaddr *)&acc_sock_addr, &asa_len); #endif if (alerted == MCC_K_TRUE) { mcc_status = MCC_S_ALERT_TERMREQ; } else { if (read_sock_d < 0) { perror("Connect accept failed.\n"); mcc_status = mcc_evc_dna_xlate_error(errno); } else /* save read_sock_d in p_iob for now */ pIO_iob->iob_w_mbx = (short int)read_sock_d; } } } return(mcc_status); } /* end mcc_evc_dna_connect_accept */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_named_close * * FUNCTIONAL DESCRIPTION: * * * * * * * * INPUT: * * pI_iob Pointer to an I/O Block * * pI_opt Pointer to optional disconnect data * * * MAJOR ALGORITHMS: * * * * MODIFICATION HISTORY: * * V1.1-0 John Purretta 04 February 1991 * Creation. * *************************************************************************/ MCC_T_CVR mcc_evc_dna_named_close ( struct MCC_R_DA_IOB *pI_iob, struct dsc_descriptor *pI_opt ) { MCC_T_Integer32 sock; /* Connection socket */ sock = pI_iob->iob_w_lnk; /* Copy stored socket into a Lword */ if ( sock != 0 ) /* If socket exists */ { close ( sock ); /* disconnect the socket */ pI_iob->iob_w_lnk = 0; /* init IOSB link field */ } return (MCC_S_NORMAL); } /************************************************************************* * * ROUTINE: * * mcc_evc_dna_named_read * * FUNCTIONAL DESCRIPTION: * create a DECnet family socket and bind * it to the object mcc_evc_sink * if any error, close the socket * * INPUT: * * * MODIFICATION HISTORY: * * V1.2-0 J. L 14-sept-1991 * Creation. * *************************************************************************/ MCC_T_CVR mcc_evc_dna_named_read (struct MCC_R_DA_IOB *pIO_named_iob, struct MCC_R_DA_IOB *pIO_iob, struct dsc_descriptor *pI_ncb, union MCC_R_DA_MBMSG_BLK *ppO_mbxmsg) { /* local variables */ MCC_T_Integer32 evc_sock_d=0,step=0 ; struct sockaddr_dn sock_dnaddr; MCC_T_CVR rs = MCC_S_NORMAL; static MCC_T_UNSBYTE sink_name[] = {'M','C','C','_','E','V','C','_','S','I','N','K'}; do { switch(step++) { case 0: /* set up end-pointer for communcation */ evc_sock_d = socket(AF_DECnet,SOCK_STREAM, 0); if (evc_sock_d < 0) { perror("Create socket failed."); rs = mcc_evc_dna_xlate_error(errno); } break; case 1: bzero((char*)&sock_dnaddr,sizeof(struct sockaddr_dn)); sock_dnaddr.sdn_family = AF_DECnet; sock_dnaddr.sdn_objnamel = sizeof(sink_name); /* mcc_evc_sink */ memcpy(sock_dnaddr.sdn_objname, sink_name, sizeof(sink_name)); if ((bind(evc_sock_d,(struct sockaddr*) &sock_dnaddr,sizeof(sock_dnaddr)) < 0)) { perror("Bind socket name mcc_evc_sink failed."); rs = mcc_evc_dna_xlate_error(errno); } break; case 2: /* save the socket for read in iob + in named iob (VD 6-06-94)*/ pIO_iob -> iob_w_lnk = evc_sock_d; pIO_named_iob -> iob_w_lnk = evc_sock_d; break; } } while ((rs == MCC_S_NORMAL) && (step <= 2)); if (rs != MCC_S_NORMAL) { step --; switch(step) { case 1: close (evc_sock_d); break; case 0: break; } } return(rs); } /* end mcc_da_named_read */ /************************************************************************* * * ROUTINE: * * mcc_evc_dna_read_mbx (Unix version) * * FUNCTIONAL DESCRIPTION: * * read from the DECnet socket corresponding to a connection * all the new bytes * (in the limit of NETMGMT_BUFFER_SIZE, defined in mcc_evcam_include.h) * No checking is done upon the socket validity * * INPUT: * * pIO_iob Pointer to an I/O Block , containing the socket id * * OUTPUT: * pIO_iob->iob_r_sb.sb_w_bytes_xferd : contains the number of bytes actually read * pO_msg Pointer to formatted message * * * * MODIFICATION HISTORY: * * V1.2-0 JL 04-Nov-1991 * Creation. * *************************************************************************/ int mcc_evc_dna_read_mbx ( struct MCC_R_DA_IOB *pIO_iob, MCC_T_Descriptor *pO_msg) { MCC_T_Integer32 bytes_read = 0, sock = 0, /* Connection socket */ status = MCC_S_NORMAL; sock = pIO_iob->iob_w_mbx; /* Copy stored socket into a Lword */ #ifndef NOT_MCC TRY bytes_read = read ( sock, pO_msg->mcc_a_pointer, (size_t)pO_msg->mcc_w_maxstrlen ); CATCH (cma_e_alerted) { bytes_read = -1 ; } ENDTRY #else bytes_read = read ( sock, pO_msg->mcc_a_pointer, (size_t)pO_msg->mcc_w_maxstrlen ); #endif if ( bytes_read >= 0 ) { pIO_iob->iob_r_sb.sb_w_bytes_xferd = (short int) bytes_read; } else { close (sock); status = mcc_evc_dna_xlate_error (errno); } return ( status ); } /* End routine mcc_evc_dna_read_mbx (Ultrix version) */