/****************************************************************************** (c) 2002-2008 Christine Caulfield christine.caulfield@googlemail.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ****************************************************************************** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dn_endian.h" #include "dnlogin.h" // If we don't have MSG_NOSIGNAL, ignore it for now // TODO: is this correct to just ignore it? #ifndef MSG_NOSIGNAL #define MSG_NOSIGNAL 0 #endif /* Foundation services messages */ #define FOUND_MSG_BIND 1 #define FOUND_MSG_UNBIND 2 #define FOUND_MSG_BINDACCEPT 4 #define FOUND_MSG_ENTERMODE 5 #define FOUND_MSG_EXITMODE 6 #define FOUND_MSG_CONFIRMMODE 7 #define FOUND_MSG_NOMODE 8 #define FOUND_MSG_COMMONDATA 9 #define FOUND_MSG_MODEDATA 10 static const char *hosttype[] = { "RT-11", "RSTS/E", "RSX-11S", "RSX-11M", "RSX-11D", "IAS", "VMS", "TOPS-20", "TOPS-10", "OS8", "RTS-8", "RSX-11M+", "DEC Unix", "??14", "??15", "??16", "??17", "Ultrix-32", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Unix-dni" }; /* Header for a single-message "common data" message */ struct common_header { char msg; char pad; unsigned short len; }; static int sockfd = -1; static int (*terminal_processor)(char *, int); static int send_bindaccept(void) { int wrote; char bindacc_msg[] = { FOUND_MSG_BINDACCEPT, 2,4,0, /* Version triplet */ 7,0, /* OS = VMS */ 0x10, /* We talk terminal protocol */ 0, /* Empty rev string */ }; wrote = write(sockfd, bindacc_msg, sizeof(bindacc_msg)); if (wrote != sizeof(bindacc_msg)) { fprintf(stderr, "%s\n", found_connerror()); return -1; } return 0; } int found_getsockfd() { return sockfd; } /* Write "Common data" with a foundation header */ int found_common_write(char *buf, int len) { struct iovec vectors[2]; struct msghdr msg; struct common_header header; DEBUG_FOUND("sending %d bytes\n", len); if (debug & DEBUG_FLAG_FOUND2) { int i; DEBUG_FOUND2("sending: "); for (i=0; in_addr, 2); if (connect(sockfd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) < 0) { fprintf(stderr, "Cannot connect to %s: %s\n", node, found_connerror()); return -1; } terminal_processor = processor; return 0; } /* Return the text of a connection error */ char *found_connerror() { int saved_errno = errno; #ifdef DSO_DISDATA struct optdata_dn optdata; unsigned int len = sizeof(optdata); char *msg; if (errno == ETIMEDOUT || getsockopt(sockfd, DNPROTO_NSP, DSO_CONDATA, &optdata, &len) == -1) { return strerror(saved_errno); } // Turn the rejection reason into text switch (optdata.opt_status) { case DNSTAT_REJECTED: msg="Rejected by object"; break; case DNSTAT_RESOURCES: msg="No resources available"; break; case DNSTAT_NODENAME: msg="Unrecognised node name"; break; case DNSTAT_LOCNODESHUT: msg="Local Node is shut down"; break; case DNSTAT_OBJECT: msg="Unrecognised object"; break; case DNSTAT_OBJNAMEFORMAT: msg="Invalid object name format"; break; case DNSTAT_TOOBUSY: msg="Object too busy"; break; case DNSTAT_NODENAMEFORMAT: msg="Invalid node name format"; break; case DNSTAT_REMNODESHUT: msg="Remote Node is shut down"; break; case DNSTAT_ACCCONTROL: msg="Login information invalid at remote node"; break; case DNSTAT_NORESPONSE: msg="No response from object"; break; case DNSTAT_NODEUNREACH: msg="Node Unreachable"; break; case DNSTAT_MANAGEMENT: msg="Abort by management/third party"; break; case DNSTAT_ABORTOBJECT: msg="Remote object aborted the link"; break; case DNSTAT_NODERESOURCES: msg="Node does not have sufficient resources for a new link"; break; case DNSTAT_OBJRESOURCES: msg="Object does not have sufficient resources for a new link"; break; case DNSTAT_BADACCOUNT: msg="The Account field in unacceptable"; break; case DNSTAT_TOOLONG: msg="A field in the access control message was too long"; break; default: msg=strerror(saved_errno); break; } return msg; #else return strerror(saved_errno); #endif }