386BSD 0.1 development
[unix-history] / usr / othersrc / contrib / isode / ssap / ssaprespond.c
CommitLineData
a0be6343
WJ
1/* ssaprespond.c - SPM: responder */
2
3#ifndef lint
4static char *rcsid = "$Header: /f/osi/ssap/RCS/ssaprespond.c,v 7.3 91/02/22 09:45:59 mrose Interim $";
5#endif
6
7/*
8 * $Header: /f/osi/ssap/RCS/ssaprespond.c,v 7.3 91/02/22 09:45:59 mrose Interim $
9 *
10 *
11 * $Log: ssaprespond.c,v $
12 * Revision 7.3 91/02/22 09:45:59 mrose
13 * Interim 6.8
14 *
15 * Revision 7.2 90/11/21 11:31:45 mrose
16 * sun
17 *
18 * Revision 7.1 89/11/27 10:30:46 mrose
19 * sync
20 *
21 * Revision 7.0 89/11/23 22:25:38 mrose
22 * Release 6.0
23 *
24 */
25
26/*
27 * NOTICE
28 *
29 * Acquisition, use, and distribution of this module and related
30 * materials are subject to the restrictions of a license agreement.
31 * Consult the Preface in the User's Manual for the full terms of
32 * this agreement.
33 *
34 */
35
36
37/* LINTLIBRARY */
38
39#include <stdio.h>
40#include "spkt.h"
41#include "tailor.h"
42
43/* \f S-CONNECT.INDICATION */
44
45int SInit (vecp, vec, ss, si)
46int vecp;
47char **vec;
48struct SSAPstart *ss;
49struct SSAPindication *si;
50{
51 int len;
52 register struct ssapblk *sb;
53 register struct ssapkt *s;
54 struct TSAPstart tss;
55 register struct TSAPstart *ts = &tss;
56 struct TSAPdisconnect tds;
57 register struct TSAPdisconnect *td = &tds;
58
59 isodetailor (NULLCP, 0);
60
61 if (vecp < 2)
62 return ssaplose (si, SC_PARAMETER, NULLCP,
63 "bad initialization vector");
64 missingP (vec);
65 missingP (ss);
66 missingP (si);
67
68 if ((sb = newsblk ()) == NULL)
69 return ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
70
71 if (vecp == 2 || TInit (vecp, vec, ts, td) != NOTOK) {
72 int sd;
73 struct TSAPdata txs;
74 register struct TSAPdata *tx = &txs;
75
76 if (vecp == 2) {
77 if (TRestoreState (vec[1], ts, td) == NOTOK) {
78 (void) ts2sslose (si, "TRestoreState", td);
79 (void) ssaplose (si, SC_PARAMETER, NULLCP,
80 "bad initialization vector");
81 goto out1;
82 }
83 bzero (vec[0], strlen (vec[0]));
84 bzero (vec[1], strlen (vec[1]));
85 *vec = NULL;
86 }
87 else {
88 if (TConnResponse (ts -> ts_sd, &ts -> ts_called,
89 ts -> ts_expedited, NULLCP, 0, NULLQOS, td) == NOTOK) {
90 (void) ts2sslose (si, "TConnResponse", td);
91 (void) TDiscRequest (ts -> ts_sd, NULLCP, 0, td);
92 goto out1;
93 }
94 }
95 sd = ts -> ts_sd;
96
97 if (TReadRequest (sb -> sb_fd = sd, tx, NOTOK, td) == NOTOK) {
98 (void) ts2sslose (si, "TReadRequest", td);
99 goto out1;
100 }
101
102 s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, NULLIP);
103 TXFREE (tx);
104
105 if (s == NULL || s -> s_errno != SC_ACCEPT) {
106 (void) spktlose (sd, si, (s ? s -> s_errno : SC_CONGEST)
107 | SC_REFUSE, NULLCP, NULLCP);
108 goto out2;
109 }
110
111 if (s -> s_code != SPDU_CN) {
112 (void) spktlose (sd, si, (s ? s -> s_errno : SC_CONGEST)
113 | SC_REFUSE, NULLCP,
114 "session protocol mangled: expected 0x%x, got 0x%x",
115 SPDU_CN, s -> s_code);
116 goto out2;
117 }
118
119 if (s -> s_mask & SMASK_CN_VRSN
120 && !(s -> s_cn_version & SB_ALLVRSNS)) {
121 (void) spktlose (sd, si, SC_VERSION | SC_REFUSE, NULLCP,
122 "version mismatch: expecting something in 0x%x, got 0x%x",
123 SB_ALLVRSNS, s -> s_cn_version);
124 goto out2;
125 }
126 }
127 else {
128 int reason;
129
130 vec += vecp - 2;
131 s = NULL;
132 if ((reason = td -> td_reason) != DR_PARAMETER
133 || TRestoreState (vec[0], ts, td) == NOTOK
134 || (s = str2spkt (vec[1])) == NULL
135 || s -> s_errno != SC_ACCEPT) {
136 if (s)
137 freespkt (s);
138 else
139 (void) ts2sslose (si, reason != DR_PARAMETER ? "TInit"
140 : "TRestoreState", td);
141 (void) ssaplose (si, SC_PARAMETER, NULLCP,
142 "bad initialization vector");
143 goto out1;
144 }
145 bzero (vec[0], strlen (vec[0]));
146 bzero (vec[1], strlen (vec[1]));
147 *vec = NULL;
148 }
149
150 sb -> sb_fd = ts -> ts_sd;
151 sb -> sb_version =
152 (s -> s_mask & SMASK_CN_VRSN)
153 ? ((s -> s_cn_version & (1 << SB_VRSN2))
154 ? SB_VRSN2 : SB_VRSN1)
155 : s -> s_ulen > SS_SIZE
156 ? SB_VRSN2 : SB_VRSN1;
157 if (ts -> ts_expedited)
158 sb -> sb_flags |= SB_EXPD;
159
160 bzero ((char *) ss, sizeof *ss);
161 ss -> ss_sd = sb -> sb_fd;
162 if (s -> s_mask & SMASK_CN_REF)
163 ss -> ss_connect = s -> s_cn_reference; /* struct copy */
164 if (s -> s_mask & SMASK_CN_OPT)
165 sb -> sb_options = s -> s_options;
166 if (s -> s_mask & SMASK_CN_ISN)
167 ss -> ss_isn = sb -> sb_V_A = sb -> sb_V_M = s -> s_isn;
168 else
169 ss -> ss_isn = SERIAL_NONE;
170 if (!(s -> s_mask & SMASK_CN_TSDU))
171 s -> s_tsdu_init = s -> s_tsdu_resp = 0;
172 if (s -> s_tsdu_init
173 < (sb -> sb_tsdu_them = GET_TSDU_SIZE (ts -> ts_tsdusize)))
174 sb -> sb_tsdu_them = s -> s_tsdu_init;
175 if (s -> s_tsdu_resp
176 < (sb -> sb_tsdu_us = GET_TSDU_SIZE (ts -> ts_tsdusize)))
177 sb -> sb_tsdu_us = s -> s_tsdu_resp;
178 if (sb -> sb_version >= SB_VRSN2) /* XXX */
179 sb -> sb_tsdu_them = sb -> sb_tsdu_us = 0;
180
181 if (s -> s_mask & SMASK_CN_SET)
182 sb -> sb_settings = ss -> ss_settings = s -> s_settings;
183 sb -> sb_requirements = (s -> s_mask & SMASK_CN_REQ ? s -> s_cn_require
184 : SR_DEFAULT) & SR_MYREQUIRE;
185 if (!ts -> ts_expedited)
186 sb -> sb_requirements &= ~SR_EXPEDITED;
187 if (!(sb -> sb_requirements & SR_HALFDUPLEX))
188 sb -> sb_requirements &= ~SR_EXCEPTIONS;
189 ss -> ss_requirements = sb -> sb_requirements;
190 ss -> ss_calling.sa_addr = ts -> ts_calling; /* struct copy */
191 if (s -> s_mask & SMASK_CN_CALLING) {
192 if ((len = s -> s_callinglen)
193 > sizeof ss -> ss_calling.sa_selector)
194 len = sizeof ss -> ss_calling.sa_selector;
195 bcopy (s -> s_calling, ss -> ss_calling.sa_selector,
196 ss -> ss_calling.sa_selectlen = len);
197 }
198 sb -> sb_initiating = ss -> ss_calling; /* struct copy */
199 ss -> ss_called.sa_addr = ts -> ts_called; /* struct copy */
200 if (s -> s_mask & SMASK_CN_CALLED) {
201 if ((len = s -> s_calledlen)
202 > sizeof ss -> ss_called.sa_selector)
203 len = sizeof ss -> ss_called.sa_selector;
204 bcopy (s -> s_called, ss -> ss_called.sa_selector,
205 ss -> ss_called.sa_selectlen = len);
206 }
207 sb -> sb_responding = ss -> ss_called; /* struct copy */
208 if ((ss -> ss_ssdusize = sb -> sb_tsdu_us - SSDU_MAGIC) < 0)
209 ss -> ss_ssdusize = ts -> ts_tsdusize - SSDU_MAGIC;
210 ss -> ss_qos = ts -> ts_qos; /* struct copy */
211 ss -> ss_qos.qos_sversion = sb -> sb_version + 1;
212 ss -> ss_qos.qos_extended = (sb -> sb_flags & SB_EXPD) ? 1 : 0;
213 copySPKTdata (s, ss);
214
215 freespkt (s);
216
217 return OK;
218
219out2: ;
220 freespkt(s);
221
222out1: ;
223 freesblk (sb);
224
225 return NOTOK;
226}
227
228/* \f S-CONNECT.RESPONSE */
229
230#define dotoken(requires,shift,bit,type) \
231{ \
232 if (sb -> sb_requirements & requires) \
233 switch (sb -> sb_settings & (ST_MASK << shift)) { \
234 case ST_CALL_VALUE << shift: \
235 switch (settings & (ST_MASK << shift)) { \
236 case ST_INIT_VALUE << shift: \
237 settings &= ~(ST_MASK << shift); \
238 settings |= ST_INIT_VALUE << shift; \
239 break; \
240 \
241 case ST_RESP_VALUE << shift: \
242 settings &= ~(ST_MASK << shift); \
243 settings |= ST_RESP_VALUE << shift; \
244 sb -> sb_owned |= bit; \
245 break; \
246 \
247 default: \
248 return ssaplose (si, SC_PARAMETER, NULLCP, \
249 "improper choice of %s token setting", type); \
250 } \
251 break; \
252 \
253 case ST_INIT_VALUE << shift: \
254 if ((settings & (ST_MASK << shift)) == (ST_RSVD_VALUE << shift)) \
255 please |= bit; \
256 settings &= ~(ST_MASK << shift); \
257 settings |= ST_INIT_VALUE << shift; \
258 break; \
259 \
260 case ST_RESP_VALUE << shift: \
261 settings &= ~(ST_MASK << shift); \
262 settings |= ST_RESP_VALUE << shift; \
263 sb -> sb_owned |= bit; \
264 break; \
265 } \
266}
267
268/* \f */
269
270int SConnResponse (sd, ref, responding, status, requirements, settings,
271 isn, data, cc, si)
272int sd;
273struct SSAPref *ref;
274struct SSAPaddr *responding;
275int status,
276 requirements,
277 settings,
278 cc;
279long isn;
280char *data;
281struct SSAPindication *si;
282{
283 int result,
284 please;
285 register struct ssapkt *s;
286 register struct ssapblk *sb;
287
288 if ((sb = findsblk (sd)) == NULL || (sb -> sb_flags & SB_CONN))
289 return ssaplose (si, SC_PARAMETER, NULLCP, "invalid session descriptor");
290 missingP (ref);
291 refmuchP (ref);
292 if (ref -> sr_vlen)
293 return ssaplose (si, SC_PARAMETER, NULLCP, "bad format for reference");
294#ifdef notdef
295 missingP (responding);
296#endif
297 if (responding)
298 sb -> sb_responding = *responding; /* struct copy */
299 switch (status) {
300 case SC_ACCEPT:
301 if (requirements & ~SR_MYREQUIRE)
302 return ssaplose (si, SC_PARAMETER, NULLCP,
303 "requirements settings not supported");
304#ifdef notdef /* screwy session protocol... */
305 if (requirements & ~sb -> sb_requirements)
306 return ssaplose (si, SC_PARAMETER, NULLCP,
307 "requirements settings not available");
308#endif
309 if ((requirements & SR_HALFDUPLEX) && (requirements & SR_DUPLEX))
310 return ssaplose (si, SC_PARAMETER, NULLCP,
311 "half-duplex and duplex services are incompatible");
312 if ((requirements & SR_EXCEPTIONS)
313 && !(requirements & SR_HALFDUPLEX))
314 return ssaplose (si, SC_PARAMETER, NULLCP,
315 "exception service requires half-duplex service");
316 sb -> sb_requirements &= requirements;
317 sb -> sb_owned = 0, please = 0;
318 dotokens ();
319 if (sb -> sb_requirements
320 & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC)) {
321 if (!(sb -> sb_requirements & SR_ACTIVITY)
322 || isn != SERIAL_NONE)
323 if (SERIAL_MIN > isn || isn > SERIAL_MAX + 1)
324 return ssaplose (si, SC_PARAMETER, NULLCP,
325 "bad choice for initial serial number");
326 }
327 else
328 if (isn != SERIAL_NONE)
329 return ssaplose (si, SC_PARAMETER, NULLCP,
330 "initial serial number invalid given requirements");
331 break;
332
333 case SC_NOTSPECIFIED:
334 case SC_CONGESTION:
335 case SC_REJECTED:
336 break;
337
338 default:
339 return ssaplose (si, SC_PARAMETER, NULLCP, "invalid result");
340 }
341 if (data == NULL)
342 cc = 0;
343 else
344 if (cc > (sb -> sb_version < SB_VRSN2 ? SC_SIZE : ENCLOSE_MAX))
345 return ssaplose (si, SC_PARAMETER, NULLCP,
346 "too much initial user data, %d octets", cc);
347 missingP (si);
348
349 if (status != SC_ACCEPT) {
350 if ((s = newspkt (SPDU_RF)) == NULL) {
351 (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
352 goto out1;
353 }
354
355 s -> s_mask |= SMASK_RF_REF;
356 s -> s_rf_reference = *ref; /* struct copy */
357 if (status == SC_REJECTED) {
358 s -> s_mask |= SMASK_RF_REQ;
359 s -> s_rf_require = requirements;
360 }
361 if ((s -> s_rdata = malloc ((unsigned) (s -> s_rlen = 1 + cc)))
362 == NULL) {
363 (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
364 goto out2;
365 }
366 *s -> s_rdata = status & 0xff;
367 if (cc > 0)
368 bcopy (data, s -> s_rdata + 1, cc);
369 result = refuse (sb, s, si);
370 freesblk (sb);
371
372 return (result != NOTOK && status != SC_ACCEPT ? OK : NOTOK);
373 }
374
375 if ((s = newspkt (SPDU_AC)) == NULL) {
376 (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
377 goto out1;
378 }
379
380 s -> s_mask |= SMASK_CN_REF | SMASK_CN_OPT | SMASK_CN_VRSN;
381 s -> s_cn_reference = *ref; /* struct copy */
382 s -> s_options = CR_OPT_NULL;
383 s -> s_cn_version = 1 << sb -> sb_version;
384
385 if (isn != SERIAL_NONE) {
386 s -> s_mask |= SMASK_CN_ISN;
387 s -> s_isn = isn;
388 }
389
390 if (sb -> sb_tsdu_us || sb -> sb_tsdu_them) {
391 s -> s_mask |= SMASK_CN_TSDU;
392 s -> s_tsdu_resp = GET_TSDU_SIZE (sb -> sb_tsdu_us);
393 s -> s_tsdu_init = GET_TSDU_SIZE (sb -> sb_tsdu_them);
394 }
395
396 s -> s_mask |= SMASK_CN_REQ;
397 if ((s -> s_cn_require = sb -> sb_requirements) & SR_TOKENS) {
398 s -> s_mask |= SMASK_CN_SET;
399 s -> s_settings = settings;
400 }
401 if (please) {
402 s -> s_mask |= SMASK_AC_TOKEN;
403 s -> s_ac_token = please;
404 }
405 if (responding) {
406 s -> s_mask |= SMASK_CN_CALLED;
407 bcopy (sb -> sb_responding.sa_selector, s -> s_called,
408 s -> s_calledlen = sb -> sb_responding.sa_selectlen);
409 }
410
411 if (cc > 0) {
412 s -> s_mask |= SMASK_UDATA_PGI;
413 s -> s_udata = data, s -> s_ulen = cc;
414 }
415 else
416 s -> s_udata = NULL, s -> s_ulen = 0;
417 if ((result = spkt2sd (s, sb -> sb_fd, 0, si)) == NOTOK)
418 freesblk (sb);
419 else
420 sb -> sb_flags |= SB_CONN;
421 s -> s_mask &= ~SMASK_UDATA_PGI;
422 s -> s_udata = NULL, s -> s_ulen = 0;
423
424 freespkt(s);
425
426 return result;
427
428out2: ;
429 freespkt (s);
430out1: ;
431 freesblk (sb);
432
433 return NOTOK;
434}
435
436#undef dotoken
437
438/* \f */
439
440static int refuse (sb, s, si)
441register struct ssapblk *sb;
442register struct ssapkt *s;
443register struct SSAPindication *si;
444{
445 int result;
446 struct TSAPdata txs;
447 register struct TSAPdata *tx = &txs;
448 struct TSAPdisconnect tds;
449 register struct TSAPdisconnect *td = &tds;
450
451 s -> s_mask |= SMASK_RF_DISC;
452 s -> s_rf_disconnect |= RF_DISC_RELEASE;
453
454 result = spkt2sd (s, sb -> sb_fd, sb -> sb_flags & SB_EXPD ? 1 : 0, si);
455
456 freespkt (s);
457 if (result == NOTOK)
458 return NOTOK;
459
460 if (ses_rf_timer >= 0)
461 switch (TReadRequest (sb -> sb_fd, tx, ses_rf_timer, td)) {
462 case OK:
463 default: /* what could this be? */
464 TXFREE (tx);
465 break;
466
467 case NOTOK:
468 sb -> sb_fd = NOTOK;
469 break;
470 }
471
472 return OK;
473}