|
|
1.1 root 1: /* psaptcp.c - PPM: TCP backing */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/psap2-lpp/RCS/ps2tcp.c,v 7.2 90/07/09 14:45:01 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/psap2-lpp/RCS/ps2tcp.c,v 7.2 90/07/09 14:45:01 mrose Exp $
9: *
10: * Contributed by The Wollongong Group, Inc.
11: *
12: *
13: * $Log: ps2tcp.c,v $
14: * Revision 7.2 90/07/09 14:45:01 mrose
15: * sync
16: *
17: * Revision 7.1 90/07/01 21:05:19 mrose
18: * pepsy
19: *
20: * Revision 7.0 89/11/23 22:15:50 mrose
21: * Release 6.0
22: *
23: */
24:
25: /*
26: * NOTICE
27: *
28: * Acquisition, use, and distribution of this module and related
29: * materials are subject to the restrictions of a license agreement.
30: * Consult the Preface in the User's Manual for the full terms of
31: * this agreement.
32: *
33: */
34:
35:
36: /* LINTLIBRARY */
37:
38: #include <stdio.h>
39: #define LPP
40: #include "PS-types.h"
41: #include "ppkt.h"
42: #include "tsap.h"
43: #include "tailor.h"
44:
45: #include "internet.h"
46: #include <errno.h>
47: #ifdef BSD42
48: #include <sys/ioctl.h>
49: #endif
50:
51: /* DATA */
52:
53: #ifdef FIONBIO
54: static fd_set inprogress;
55: static struct sockaddr_in *peers = NULL;
56: #endif
57:
58: extern int errno;
59:
60: /* */
61:
62: int tcpopen (pb, calling, called, pi, async)
63: register struct psapblk *pb;
64: struct NSAPaddr *calling,
65: *called;
66: struct PSAPindication *pi;
67: int async;
68: {
69: int fd;
70: #ifdef FIONBIO
71: int onoff;
72: #endif
73: struct sockaddr_in lo_socket,
74: in_socket;
75: register struct sockaddr_in *lsock = &lo_socket,
76: *isock = &in_socket;
77: register struct hostent *hp;
78:
79: #ifndef FIONBIO
80: if (async)
81: return psaplose (pi, PC_PARAMETER, NULLCP,
82: "asynchronous not supported");
83: #endif
84:
85: bzero ((char *) isock, sizeof *isock);
86:
87: if (called -> na_port == 0)
88: return psaplose (pi, PC_ADDRESS, NULLCP,
89: "TCP port of called address not specified");
90: else
91: isock -> sin_port = called -> na_port;
92:
93: if ((hp = gethostbystring (called -> na_domain)) == NULL)
94: return psaplose (pi, PC_ADDRESS, NULLCP, "%s: unknown host",
95: called -> na_domain);
96: #ifdef notanymore
97: (void) strncpy (called -> na_domain, hp -> h_name,
98: sizeof called -> na_domain);
99: #endif
100:
101: isock -> sin_family = hp -> h_addrtype;
102: inaddr_copy (hp, isock);
103:
104: #ifndef notanymore
105: (void) strcpy (called -> na_domain, inet_ntoa (isock -> sin_addr));
106: #endif
107:
108: if (calling && calling -> na_domain[0]) {
109: bzero ((char *) lsock, sizeof *lsock);
110:
111: if ((hp = gethostbystring (calling -> na_domain)) == NULL)
112: return psaplose (pi, PC_ADDRESS, NULLCP, "%s: unknown host",
113: calling -> na_domain);
114:
115: if ((lsock -> sin_family = hp -> h_addrtype) != isock -> sin_family)
116: return psaplose (pi, PC_ADDRESS, NULLCP,
117: "address family mismatch");
118:
119: inaddr_copy (hp, lsock);
120: }
121: else
122: lsock = NULL;
123:
124: if ((fd = start_tcp_client (lsock, 0)) == NOTOK)
125: return psaplose (pi, PC_CONGEST, "socket", "unable to start");
126:
127: #ifdef FIONBIO
128: if (async)
129: (void) ioctl (fd, FIONBIO, (onoff = 1, (char *) &onoff));
130: #endif
131: PTservice (pb, fd);
132:
133: if (join_tcp_server (fd, isock) == NOTOK) {
134: #ifdef FIONBIO
135: if (async)
136: switch (errno) {
137: case EINPROGRESS:
138: if (peers == NULL) {
139: peers = (struct sockaddr_in *)
140: calloc ((unsigned) getdtablesize (),
141: sizeof *peers);
142: if (peers == NULL) {
143: (void) psaplose (pi, PC_CONGEST, NULLCP,
144: "out of memory");
145: (void) close_tcp_socket (fd);
146: return (pb -> pb_fd = NOTOK);
147: }
148:
149: FD_ZERO (&inprogress);
150: }
151: FD_SET (fd, &inprogress);
152: peers[fd] = *isock;/* struct copy */
153: return OK;
154:
155: case EISCONN:
156: goto done;
157:
158: default:
159: break;
160: }
161: #endif
162:
163: (void) psaplose (pi, PC_REFUSED, "connection", "unable to establish");
164: (void) close_tcp_socket (fd);
165: return (pb -> pb_fd = NOTOK);
166: }
167: #ifdef FIONBIO
168: done: ;
169:
170: if (async)
171: (void) ioctl (fd, FIONBIO, (onoff = 0, (char *) &onoff));
172: #endif
173:
174: if (tcpready (pb, pi) == NOTOK) {
175: (void) close_tcp_socket (fd);
176: pb -> pb_fd = NOTOK;
177: }
178:
179: return DONE;
180: }
181:
182: /* */
183:
184: /* ARGSUSED */
185:
186: char *tcpsave (fd, sin, cp1, cp2, td)
187: int fd;
188: struct sockaddr_in *sin;
189: char *cp1,
190: *cp2;
191: struct TSAPdisconnect *td;
192: {
193: static char buffer[BUFSIZ];
194:
195: (void) sprintf (buffer, "%c%d %s %s", PT_TCP, fd, cp1, cp2);
196:
197: return buffer;
198: }
199:
200:
201: int tcprestore (pb, buffer, pi)
202: register struct psapblk *pb;
203: char *buffer;
204: struct PSAPindication *pi;
205: {
206: int fd;
207: char domain[NSAP_DOMAINLEN + 1];
208: register struct NSAPaddr *na;
209:
210: na = &pb -> pb_initiating;
211: na -> na_stack = NA_TCP;
212: na -> na_community = ts_comm_tcp_default;
213:
214: if (sscanf (buffer, "%d %s %s", &fd, na -> na_domain, domain) != 3
215: || fd < 0)
216: return psaplose (pi, PC_PARAMETER, NULLCP,
217: "bad initialization vector");
218:
219: PTservice (pb, fd);
220:
221: na = pb -> pb_responding.pa_addr.sa_addr.ta_addrs;
222: na -> na_stack = NA_TCP;
223: na -> na_community = ts_comm_tcp_default;
224: (void) strncpy (na -> na_domain, domain, sizeof na -> na_domain);
225:
226: if ((pb -> pb_stream = ps_alloc (fdx_open)) == NULLPS
227: || fdx_setup (pb -> pb_stream, pb -> pb_fd) == NOTOK)
228: return psaplose (pi, PC_CONGEST, NULLCP, NULLCP);
229:
230: return OK;
231: }
232:
233: /* */
234:
235: static int tcpretry (pb, pi)
236: register struct psapblk *pb;
237: struct PSAPindication *pi;
238: {
239: #ifdef FIONBIO
240: int onoff;
241: int fd = pb -> pb_fd;
242: fd_set mask;
243: struct sockaddr_in *isock = &peers[fd];
244:
245: if (!FD_SET (fd, &inprogress))
246: return psaplose (pi, PC_PARAMETER, NULLCP,
247: "connection not in progress");
248: FD_ZERO (&mask);
249: FD_SET (fd, &mask);
250:
251: if (xselect (fd + 1, NULLFD, &mask, NULLFD, 0) < 1)
252: return OK;
253:
254: isock = &peers[fd];
255: if (join_tcp_server (fd, isock) == NOTOK) {
256: switch (errno) {
257: case EINPROGRESS:
258: return OK;
259:
260: case EISCONN:
261: goto done;
262:
263: case EINVAL: /* UNIX bug: could be any socket errno, e.g.,
264: ETIMEDOUT */
265: errno = ECONNREFUSED;
266: /* and fall */
267: default:
268: break;
269: }
270:
271: (void) psaplose (pi, PC_REFUSED, "connection", "unable to establish");
272: FD_CLR (fd, &inprogress);
273: (void) close_tcp_socket (fd);
274: return (pb -> pb_fd = NOTOK);
275: }
276: done: ;
277:
278: (void) ioctl (fd, FIONBIO, (onoff = 0, (char *) &onoff));
279: FD_CLR (fd, &inprogress);
280:
281: if (tcpready (pb, pi) == NOTOK) {
282: (void) close_tcp_socket (fd);
283: return (pb -> pb_fd = NOTOK);
284: }
285:
286: return DONE;
287: #else
288: return psaplose (pi, PC_OPERATION, NULLCP, "connection not in progress");
289: #endif
290: }
291:
292: /* */
293:
294: static int tcpready (pb, pi)
295: register struct psapblk *pb;
296: struct PSAPindication *pi;
297: {
298: PS ps;
299:
300: if ((pb -> pb_stream = ps_alloc (fdx_open)) == NULLPS
301: || fdx_setup (pb -> pb_stream, pb -> pb_fd) == NOTOK)
302: return psaplose (pi, PC_CONGEST, NULLCP, NULLCP);
303:
304: PLOGP (psap2_log,PS_PDUs, pb -> pb_retry, "ConnectRequest-PDU", 0);
305:
306: if (pe2ps (ps = pb -> pb_stream, pb -> pb_retry) == NOTOK)
307: return pslose (pi, ps -> ps_errno);
308:
309: pe_free (pb -> pb_retry);
310: pb -> pb_retry = NULLPE;
311:
312: if ((pb -> pb_response = ps2pe (pb -> pb_stream)) == NULLPE)
313: return pslose (pi, ps -> ps_errno);
314:
315: return OK;
316: }
317:
318: /* */
319:
320: #define tcpclose close_tcp_socket
321: #define tcpselect select_tcp_socket
322:
323:
324: static int PTservice (pb, fd)
325: register struct psapblk *pb;
326: int fd;
327: {
328: pb -> pb_fd = fd;
329:
330: pb -> pb_reliability = HIGH_QUALITY;
331:
332: pb -> pb_retryfnx = tcpretry;
333: pb -> pb_closefnx = tcpclose;
334: pb -> pb_selectfnx = tcpselect;
335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.