📄 xti.c
字号:
#ifndef lintstatic char *sccsid = "@(#)xti.c 4.2 (ULTRIX) 11/14/90";#endif lint/*********************************************************************** * * Copyright (c) Digital Equipment Corporation, 1990 * All Rights Reserved. Unpublished - rights reserved * under the copyright laws of the United States. * * The software contained on this media is proprietary * to and embodies the confidential technology of * Digital Equipment Corporation. Possession, use, * duplication or dissemination of the software and * media is authorized only pursuant to a valid written * license from Digital Equipment Corporation. * * RESTRICTED RIGHTS LEGEND Use, duplication, or * disclosure by the U.S. Government is subject to * restrictions as set forth in Subparagraph (c)(1)(ii) * of DFARS 252.227-7013, or in FAR 52.227-19, or in * FAR 52.227-14 ALT.III, as applicable. * ***********************************************************************//************************************************************************ * Modification History * * * 07/20/87 hu Original code. * 12/02/87 mcmenemy Added additional library functionality * 01/19/88 mcmenemy Added connection-less support * 02/01/88 mcmenemy clean-up - prepare to release 1st prototype * which includes DECnet Ultrix support * 03/07/88 mcmenemy Update to Revision 2 (24-feb-88) at GRENOBLE * 03/29/88 mcmenemy Fix dynamic indexing. * 04/06/88 mcmenemy Make changes for BL2 * 08/25/88 mcmenemy Update to Final Draft for XPG 3 * 10/09/88 mcmenemy Get rid of clearing some events that will be kernel * 11/09/88 mcmenemy Clean-up (ie. move ENEVENT to socket call and * explicitly disable events in T_UNBIND * 11/26/88 mcmenemy Add *_CONOPT support,enhance T_OPTMGMT, finish T_MORE. * 12/01/88 mcmenemy Add t_alloc() and t_free() support. * 12/06/88 mcmenemy Cleanup NSP code ,add XTIXPG4 defines and OSI code. * 01/06/89 mcmenemy Modify t_accept handling of socket address. * 01/08/89 mcmenemy Add AF_OSI code for defer mode in t_listen * 02/02/89 mcmenemy Add code to clear T_DISCONNECT event in t_rcvdis(). * 02/10/89 mcmenemy Clean-up d_table usage. * 02/20/89 mcmenemy Add additional error return from t_bind. * 02/21/89 mcmemeny Performance enhancements * 03/08/89 mcmenemy Change event handling algorithmn * 03/09/89 mcmenemy Add address generation to t_bind + mapping errors * returns to match verification spec. * 03/10/89 mcmenemy Put update check code back into t_close * 03/10/89 mcmenemy In t_snddis make sure call is valid before checking * call->sequence * 03/13/89 mcmenemy In t_snddis call XTIABORT setsockopt even in * T_DATAXFER state (instead of shutdown - which * would generate a T_ORDREL event. * 03/15/89 mcmenemy Change handling of error return for * TNOTSUPPORT/TBADDATA * 04/04/89 mcmenemy Fix t_unbind , make setsockopt call to unbind(zero) * pertinent fields without deleting control blocks. * This will allow for t_bind()-t-unbind() loops to work. * Place event enabling where endpoint becomes active * (ie. t_bind()) * 04/05/89 mcmenemy If rcvcall is not used in t_connect, don't use it. * 04/24/89 mcmenemy Make t_sndrel conformance to spec. * 04/27/89 mcmenemy Check for NULL call parameter in t_snddis. * 04/27/89 mcmenemy Re-add PEEK flag in t_rcv to set/clear T_MORE flag * 05/02/89 mcmenemy LINT. * 05/10/89 mcmenemy Add additional event syncronization in t_look. * This feature may be turned off by XTI_UNEVENT. * 07/14/89 mcmenemy Fix XPG3 Conformance bugs * 09/12/89 Ron B. Fix segmentation fault in t_rcv on MIPS. * 11/22/89 Ron B. Retrieve any user data sent by the caller in the * t_listen call. * 02/23/90 Ron B. Returns the responding protocol address to the user * in t_connect call. * 03/05/90 Ron B. Switch over to use new osi.h. * When checking the length of protocol address against * the maximum protocol address size in t_info table, * take "-1" and "-2" into account. * Rewrite how t_accept does the checking. * Change to use new socket option name. * 04/11/90 Ron B. Make sure that we don't linger on t_close for OSI. * 05/17/90 Ron B. Fix accept checking for TCP. * 08/08/90 gray Do not set acceptmode, nor listen if CLTS in * t_bind(). Inititalise seq. no in t_listen(). * Allow auto-addr generation for OSI. (courtesy * Matt Thomas). * 11/06/90 gray Misc bug fixes to prevent various user areas * being overwritten. Conformance fixes to most * functions. * 11/14/90 heather Merge changes, including from 11/22/89 above, * into ULTRIX source pool. * ************************************************************************//* * XTI Library: xti.c * * This module provides the transport layer programming interface defined * in the X/OPEN Portability Guide: Networking Services. *//*LINTLIBRARY*/#define XTI 1#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <malloc.h>#include <sys/time.h>#include <sys/ioctl.h>#include <sys/xti.h>#include <netinet/tcp.h>#include <netinet/udp.h>#include "xti_lib.h"extern char *allocate_addr();extern char *allocate_opt();extern char *allocate_udata();extern void bcopy();extern void perror();extern void map_err_to_XTI();/* * macro */#define table(fd) ((*d_table.dcb)[fd]) /* define macro for dynamic table */#define MAX(x,y) ((x > y) ? x : y )/* * T_ACCEPT - accept a connect request */int t_accept (fd, resfd, call)int fd; /* where the connection indication arrived */int resfd; /* where the connection is to be established */struct t_call *call;{#ifdef XTINSP struct accessdata_dn nsp_accessdata;#endif int status; int optl; int old_state; int chklen; /* total length of accept_check structure */ struct xti_evtinfo evtinfo; struct accept_check { int resfd; int seqnum; union { struct sockaddr generic;#ifdef XTIOSI struct sockaddr_osi osi;#endif XTIOSI } addr; /* sockaddr_osi must be the last one in structure */ } *chk; if (!(check_xtifd(fd))) { t_errno = TBADF; return(-1); } if (!(check_xtifd(resfd))) { t_errno = TBADF; return(-1); } /* * Must make sure we have dynamic table built. */ if (d_table.dcb == T_NULL) { t_errno = TBADF; return(-1); } old_state = table(fd).state; if ( (check_XTI_state(fd, XTI_ACCEPT1) == -1) && (check_XTI_state(fd, XTI_ACCEPT2) == -1) && (check_XTI_state(fd, XTI_ACCEPT3) == -1) ) { t_errno = TOUTSTATE; return(-1); } if ( (fd != resfd) && (check_XTI_state(resfd ,XTI_LISTEN) == -1) ) { t_errno = TOUTSTATE; return(-1); } if ( (fd != resfd) && (table(resfd).state != T_IDLE)) { t_errno = TOUTSTATE; return(-1); } if (table(fd).info.servtype != T_COTS && table(fd).info.servtype != T_COTS_ORD) { t_errno = TNOTSUPPORT; return(-1); } if (fd != resfd) { if (table(resfd).info.servtype != T_COTS && table(resfd).info.servtype != T_COTS_ORD) { t_errno = TNOTSUPPORT; return(-1); } } /* * do some up-front checking */ if (call->sequence <= 0) { t_errno = TBADSEQ; return(-1); } /* * If the user has received other indications on this endpoint and has * not responded to them, DO NOT allow the user to accept a connection on * the same endpoint */ if ((resfd == fd) && (table(fd).cnt_outs_con_ind > 1)) { t_errno = TBADF; return(-1); } if (table(fd).info.addr != -1 && table(fd).info.addr != -2) if (call->addr.len > table(fd).info.addr) { t_errno = TBADADDR; return(-1); } /* * Determine the actual length of the accept_check since the addr portion * can be variable length. */ switch(table(fd).family) { case AF_INET: chklen = sizeof(struct accept_check); break;#ifdef XTIOSI case AF_OSI: chklen = sizeof(struct accept_check) + ((struct sockaddr_osi *)call->addr.buf)->osi_length; break;#endif XTIOSI#ifdef XTINSP case AF_DECnet: chklen = 0; /* we don't yet support NSP */ break;#endif XTINSP } /* * Get buffer to pass information to be checked to the kernel. * Then, load the buffer with the information. This buffer * will be passed to the kernel for actual checking. */ chk = (struct accept_check *)malloc(chklen); chk->seqnum = call->sequence; chk->resfd = resfd; bcopy( call->addr.buf, (char *)&chk->addr.generic, (int)call->addr.len); /* * Check to see if any event pending. */ status = xti_peek(fd, &evtinfo); if (status == -1) { free(chk); return(-1); } if (evtinfo.evtarray[ffs(T_LISTEN)] || evtinfo.evtarray[ffs(T_DISCONNECT)]) { free(chk); t_errno = TLOOK; return(-1); } /* * Send user data (if any) */ if (call->udata.len > 0) { if (table(resfd).info.connect == T_NOTSUPPORTED) { t_errno = TBADDATA; return(-1); } if (call->udata.len > (table(resfd).info.connect)) { t_errno = TBADDATA; return(-1); } switch(table(fd).family) { case AF_INET: break;#ifdef XTIOSI case AF_OSI: { char *usrdat; int usrdatlen = table(resfd).info.connect; usrdat = (char *)malloc(usrdatlen); if (usrdat == NULL) { t_errno = TSYSERR; errno = ENOBUFS; return(-1); } bzero(usrdat, usrdatlen); bcopy(call->udata.buf, usrdat, call->udata.len); status = setsockopt(resfd, OSIPROTO_COTS, TOPT_OPTCONDATA, usrdat, call->udata.len); free(usrdat); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break; }#endif#ifdef XTINSP case AF_DECnet: optl = call->udata.len; status = setsockopt(resfd, DNPROTO_NSP, DSO_CONDATA, call->udata.buf, optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif }; } /* * Send option data (if any) */ if (call->opt.len > 0) { if (table(fd).info.options == T_NOTSUPPORTED) { t_errno = TNOTSUPPORT; return(-1); } if (call->opt.len > table(fd).info.options) { t_errno = TBADOPT; return(-1); } switch(table(fd).family) {#ifdef XTIOSI case AF_OSI: { int tmp_len; tmp_len = call->opt.len; status = setsockopt(resfd, OSIPROTO_COTS, TOPT_XTICONOPTS, call->opt.buf, tmp_len ); if (status == -1) { map_err_to_XTI(errno,&t_errno); if (t_errno == TNOTSUPPORT) t_errno = TBADOPT; /* re-map */ return(-1); } } break;#endif case AF_INET: if (table(fd).xti_proto == IPPROTO_TCP) { int tmp_len; tmp_len = call->opt.len; status = setsockopt(resfd, IPPROTO_TCP, TCP_CONOPT, call->opt.buf, tmp_len ); if (status == -1) { map_err_to_XTI(errno,&t_errno); if (t_errno == TNOTSUPPORT) t_errno = TBADOPT; /* re-map */ return(-1); } } break;#ifdef XTINSP case AF_DECnet: bcopy(call->opt.buf,(char *) &nsp_accessdata, call->opt.len); optl = sizeof(struct accessdata_dn); status = setsockopt(resfd, DNPROTO_NSP, DSO_CONACCESS, (char *) &nsp_accessdata, optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif }; } /* * deferred accept */ status = setsockopt(fd, SOL_SOCKET, SO_XTIACCEPTCHK, (char *)chk, chklen); if (status < 0) { if (errno == EINVAL) { /* special case */ free(chk); t_errno = TBADSEQ; return(-1); } if (errno == EADDRNOTAVAIL || errno == EPROTONOSUPPORT) { /* special case */ free(chk); t_errno = TBADADDR; return(-1); } map_err_to_XTI(errno,&t_errno); free(chk); return(-1); } free(chk); status = setsockopt(resfd, SOL_SOCKET, SO_XTISYNC, (char *) 0, 0); if (status < 0) { map_err_to_XTI(errno,&t_errno); return(-1); } /* * Accept the connection */ switch(table(fd).family) {#ifdef XTIOSI case AF_OSI: status = setsockopt(resfd, OSIPROTO_COTS, TOPT_ACCEPT, (char *)0, 0); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif case AF_INET: switch(table(fd).xti_proto) { case IPPROTO_TCP: status = setsockopt(resfd, IPPROTO_TCP, TCP_CONACCEPT, (char *) 0,0); if (status < 0) { t_errno = TSYSERR; return(-1); } break; default: break; }; break;#ifdef XTINSP case AF_DECnet: status = setsockopt(resfd, DNPROTO_NSP, DSO_CONACCEPT, (char *) 0, 0); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif default: break; }; /* * re-load new states. */ if (resfd != fd) { old_state = t_getstate(fd); /* re-get new state */ (void) t_getstate(resfd); } /* * Update XTI state tables * */ if ( (table(fd).cnt_outs_con_ind == 1) && (fd == resfd)) { table(fd).event = XTI_ACCEPT1; /* T_ACCEPT successful */ if (update_XTI_state(fd, resfd, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } } else if ( (table(fd).cnt_outs_con_ind == 1) && (fd != resfd)) { if (table(resfd).active_flag != 1) { t_errno = TOUTSTATE; return(-1); } /* * Update XTI state tables * */ table(fd).event = XTI_ACCEPT2; /* T_ACCEPT successful */ if (update_XTI_state(fd, resfd, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } } else /* * Update XTI state tables * */ /* * This case impiles that fd != resfd */ if (table(fd).cnt_outs_con_ind > 1) { table(fd).event = XTI_ACCEPT3; /* T_ACCEPT successful */ if (update_XTI_state(fd, resfd, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } } return (0);}/* * T_ALLOC - allocate a library structure (optional) */char *t_alloc (fd, struct_type, fields)int fd;int struct_type;int fields;{ char *tmp_ptr = T_NULL; char *tmp_addr = T_NULL; char *tmp_opt = T_NULL; char *tmp_udata = T_NULL; int size; if (!(check_xtifd(fd))) { t_errno = TBADF; return(T_NULL); } switch(struct_type) { case T_BIND_STR: tmp_ptr = (char *)malloc(sizeof(struct t_bind)); if (tmp_ptr == T_NULL) { t_errno = TSYSERR; errno = ENOBUFS; return(T_NULL); } if (fields & T_ADDR) { /* ADDRESS */ if (table(fd).info.addr == -1) { /* can't allocate infinity */ free(tmp_ptr); t_errno = TSYSERR; errno = EINVAL; return(T_NULL); } tmp_addr = allocate_addr(struct_type, tmp_ptr, tmp_opt, tmp_udata, (int) table(fd).info.addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -