📄 xti.c
字号:
} break; } /* * Update XTI state tables * * Update internal tables + kernel before blowing * away endpoint * */ table(fd).event = XTI_CLOSED; if (update_XTI_state(fd, -1, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } table(fd).active_flag = -1; /* no longer valid */ table(fd).sequence = 0; table(fd).qlen = 0; if (close(fd) < 0) { map_err_to_XTI(errno,&t_errno); return (-1); } return (0);}/* * T_CONNECT - establish a connection with another transport endpoint */int t_connect (fd, sndcall, rcvcall) int fd; struct t_call *sndcall; struct t_call *rcvcall;{#ifdef XTINSP struct accessdata_dn nsp_accessdata;#endif int status; int optl; int old_state; struct xti_evtinfo evtinfo; int buffer_overflow = 0; if (!(check_xtifd(fd))) { t_errno = TBADF; return(-1); } if (d_table.dcb == T_NULL) { /* must make sure we have dynamic table built */ t_errno = TBADF; return(-1); } old_state = table(fd).state; if ( (check_XTI_state(fd, XTI_CONNECT1) == -1) && (check_XTI_state(fd, XTI_CONNECT2) == -1) ) { t_errno = TOUTSTATE; return(-1); } if (table(fd).info.servtype != T_COTS && table(fd).info.servtype != T_COTS_ORD) { t_errno = TNOTSUPPORT; return(-1); } /* * check for any incoming T_DISCONNECT's or T_LISTEN's */ status = xti_peek(fd, &evtinfo); if (status == -1) return(-1); if (evtinfo.evtarray[ffs(T_LISTEN)] || evtinfo.evtarray[ffs(T_DISCONNECT)]) { t_errno = TLOOK; return(-1); } /* check address */ if (table(fd).info.addr != -1 && table(fd).info.addr != -2) if (sndcall->addr.len > table(fd).info.addr) { t_errno = TBADADDR; return(-1); } /* * Send USER DATA */ if (sndcall->udata.len > 0) { if (table(fd).info.connect == T_NOTSUPPORTED) { t_errno = TBADDATA; return(-1); } if (sndcall->udata.len > table(fd).info.connect) { t_errno = TBADDATA; return(-1); } switch (table(fd).family) {#ifdef XTIOSI case AF_OSI: { char *usrdat; int usrdatlen = table(fd).info.connect; usrdat = (char *)malloc(usrdatlen); if (usrdat == NULL) { t_errno = TSYSERR; errno = ENOBUFS; return(-1); } bzero(usrdat, usrdatlen); bcopy(sndcall->udata.buf, usrdat, sndcall->udata.len); status = setsockopt(fd, OSIPROTO_COTS, TOPT_OPTCONDATA, usrdat, sndcall->udata.len); free(usrdat); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break; }#endif case AF_INET: break;#ifdef XTINSP case AF_DECnet: status = setsockopt(fd, DNPROTO_NSP, DSO_CONDATA, sndcall->udata.buf, sndcall->udata.len ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif }; /* end switch */ } /* end user data */ /* * Send option data (if any) */ if (sndcall->opt.len > 0) { if (table(fd).info.options == T_NOTSUPPORTED) { t_errno = TNOTSUPPORT; return(-1); } if (sndcall->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 = sndcall->opt.len; status = setsockopt(fd, OSIPROTO_COTS, TOPT_XTICONOPTS, sndcall->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 = sndcall->opt.len; status = setsockopt(fd, IPPROTO_TCP, TCP_CONOPT, sndcall->opt.buf, tmp_len );#ifdef XTISECURE#define SECURE_OPT_SIZE_ALIGN 12 { char *tmp; char *tmp1; struct tcp_options tmp_tcpopt; short security; short compartment; short handling; long tcc; int tmp_stat; bcopy(sndcall->opt.buf, &tmp_tcpopt, sizeof(struct tcp_options)); security = htons(tmp_tcpopt.secopt.security); compartment = htons(tmp_tcpopt.secopt.compartment); handling = htons(tmp_tcpopt.secopt.handling); tcc = htonl(tmp_tcpopt.secopt.tcc); if (!(security == T_UNUSED && compartment == T_UNUSED && handling == T_UNUSED && tcc == T_UNUSED)) { tmp = (char *)malloc(SECURE_OPT_SIZE_ALIGN); tmp1 = tmp; *tmp++ = 130; /* SECURITY */ *tmp++ = SECURE_OPT_SIZE_ALIGN -1; bcopy(&security, tmp, sizeof(short)); tmp += sizeof(short); bcopy(&compartment, tmp, sizeof(short)); tmp += sizeof(short); bcopy(&handling, tmp, sizeof(short)); tmp += sizeof(short); bcopy(&tcc, tmp, sizeof(long)); tmp += sizeof(long) - 1; *tmp = 0; tmp_stat = setsockopt(fd, IPPROTO_IP, IP_OPTIONS, tmp1, SECURE_OPT_SIZE_ALIGN); if (tmp_stat == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } /* * force success for CONOPT because security options * will cause error */ status = 0; } }#endif 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(sndcall->opt.buf,(char *) &nsp_accessdata, sndcall->opt.len); optl = sizeof(struct accessdata_dn); status = setsockopt(fd, DNPROTO_NSP, DSO_CONACCESS, (char *) &nsp_accessdata, optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } break;#endif }; } /* * Initialize rcvcall if specified */ if (rcvcall) { rcvcall->addr.len = 0; rcvcall->opt.len = 0; rcvcall->udata.len = 0; } if ((connect(fd, (struct sockaddr *) sndcall->addr.buf, (int) sndcall->addr.len)) == -1) { map_err_to_XTI(errno,&t_errno); if (t_errno == TNODATA) { if (rcvcall) { rcvcall->addr.len = sndcall->addr.len; rcvcall->addr.buf = sndcall->addr.buf; rcvcall->opt.buf = 0; rcvcall->udata.buf = 0; } /* * Update XTI state tables * */ table(fd).event = XTI_CONNECT2; if (update_XTI_state(fd, -1, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } return (-1); } /* * Check for user (disconnect) data */ if (rcvcall) if (rcvcall->udata.maxlen > 0) { if (table(fd).info.discon == T_NOTSUPPORTED) { t_errno = TNOTSUPPORT; return(-1); } if (rcvcall) switch (table(fd).family) {#ifdef XTIOSI case AF_OSI: optl = rcvcall->udata.maxlen; status = getsockopt(fd, OSIPROTO_COTS, TOPT_OPTDISDATA, (char *) rcvcall->udata.buf, &optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } rcvcall->udata.len = optl; break;#endif case AF_INET: break;#ifdef XTINSP case AF_DECnet: optl = rcvcall->udata.maxlen; status = getsockopt(fd, DNPROTO_NSP, DSO_DISDATA, rcvcall->udata.buf, &optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } rcvcall->udata.len = optl; break;#endif }; } return (-1); } /* end of connect error */ else { if (rcvcall) { if (rcvcall->addr.maxlen >= sndcall->addr.len) { rcvcall->addr.len = sndcall->addr.len; bcopy(sndcall->addr.buf, rcvcall->addr.buf, rcvcall->addr.maxlen); } else { buffer_overflow = 1; } if (rcvcall->udata.maxlen > 0) { switch(table(fd).family) {#ifdef XTIOSI case AF_OSI: { char *usrdat; int usrdatlen = table(fd).info.connect; usrdat = (char *)malloc(usrdatlen); if (usrdat == NULL) { t_errno = TSYSERR; errno = ENOBUFS; return(-1); } bzero(usrdat, usrdatlen); status = getsockopt(fd, OSIPROTO_COTS, TOPT_OPTCONDATA, usrdat, &usrdatlen); if (status == -1) { free(usrdat); map_err_to_XTI(errno,&t_errno); return(-1); } if (rcvcall->udata.maxlen < usrdatlen) { buffer_overflow = 1; } if (!buffer_overflow) { bcopy(usrdat, rcvcall->udata.buf, usrdatlen); rcvcall->udata.len = usrdatlen; } free(usrdat); break; }#endif case AF_INET: break;#ifdef XTINSP case AF_DECnet: optl = rcvcall->udata.maxlen; status = getsockopt(fd, DNPROTO_NSP, DSO_CONDATA, rcvcall->udata.buf, &optl ); if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } rcvcall->udata.len = optl; break;#endif }; } } /* if rcvcall */ if (rcvcall) if (rcvcall->opt.maxlen > 0) { if (rcvcall->opt.maxlen < table(fd).info.options) { buffer_overflow = 1; } if (!buffer_overflow) { switch(table(fd).family) { case AF_INET: if (table(fd).xti_proto == IPPROTO_TCP) { int tmp_len; /* here we go, let's get it from the kernel */ tmp_len = rcvcall->opt.maxlen; status = getsockopt(fd, IPPROTO_TCP, TCP_CONOPT, rcvcall->opt.buf, &tmp_len ); rcvcall->opt.len = tmp_len; if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } } break;#ifdef XTIOSI case AF_OSI: { int tmp_len; tmp_len = rcvcall->opt.maxlen; status = getsockopt(fd, OSIPROTO_COTS, TOPT_XTICONOPTS, rcvcall->opt.buf, &tmp_len ); rcvcall->opt.len = tmp_len; if (status == -1) { map_err_to_XTI(errno,&t_errno); return(-1); } } break;#endif #ifdef XTINSP case AF_DECnet: break;#endif }; } } /* * Update XTI state tables * */ table(fd).event = XTI_CONNECT1; if (update_XTI_state(fd, -1, old_state) == -1) { t_errno = TOUTSTATE; return(-1); } if (buffer_overflow) { t_errno = TBUFOVFLW; return(-1); } return (0); }}/* * T_ERROR - produce error message (optional) */char *t_errlist[] = { "Error 0", "Incorrect addr. format", /* TBADADDR 1 */ "Incorrect option format", /* TBADOPT 2 */ "Incorrect permissions", /* TACCES 3 */ "Illegal transport fd", /* TBADF 4 */ "Couldn't allocate addr", /* TNOADDR 5 */ "Out of state", /* TOUTSTATE 6 */ "Bad call sequence number", /* TBADSEQ 7 */ "System error", /* TSYSERR 8 */ "Event requires attention", /* TLOOK 9 */ "Illegal amount of data", /* TBADDATA 10 */ "Buffer not large enough", /* TBUFOVFLW 11 */ "Flow control", /* TFLOW 12 */ "No data", /* TNODATA 13 */ "Discon_ind not found on q", /* TNODIS 14 */ "Unitdata error not found", /* TNOUDERR 15 */ "Bad flags", /* TBADFLAG 16 */ "No ord rel found on q", /* TNOREL 17 */ "Primitive not supported", /* TNOTSUPPORT 18 */ "State is in process of changing", /* TSTATECHNG 19 */ "Unsupported struc-type requested", /* TNOSTRUCTYPE 20 */ "Invalid transport provider name", /* TBADNAME 21 */ "Qlen is zero", /* TBADQLEN 22 */ "Address in use", /* TADDRBUSY 23 */ }; int t_nerr = (sizeof t_errlist / sizeof t_errlist[0]);int t_errno; /* definition for t_errno */intt_error (errmsg)char *errmsg;{ extern int t_errno; extern char *t_errlist[]; extern int t_nerr; if (t_errno <0 || t_errno > t_nerr) { t_errno=TSYSERR; errno=EINVAL; return(-1); /* protect ourselves */ } write(2,errmsg,strlen(errmsg)); write(2,":\t",strlen(":\t")); write(2,t_errlist[t_errno],strlen(t_errlist[t_errno])); write(2,"\n",sizeof("\n")); if (t_errno == TSYSERR) { perror(""); } return(0);}/* * T_FREE - free a library structure (optional) */int t_free (ptr, struct_type)char *ptr;int struct_type;{ if (ptr == T_NULL) { t_errno = TSYSERR; errno = EINVAL; return(-1); } switch(struct_type) { case T_BIND_STR: if (((struct t_bind *)ptr)->addr.buf) free(((struct t_bind *)ptr)->addr.buf); free(ptr); break; case T_OPTMGMT_STR: if (((struct t_optmgmt *)ptr)->opt.buf) free(((struct t_optmgmt *)ptr)->opt.buf); free(ptr); break; case T_CALL_STR: if (((struct t_call *)ptr)->addr.buf) free(((struct t_call *)ptr)->addr.buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -