|
|
1.1 root 1: /***********************************************************
2: Copyright IBM Corporation 1987
3:
4: All Rights Reserved
5:
6: Permission to use, copy, modify, and distribute this software and its
7: documentation for any purpose and without fee is hereby granted,
8: provided that the above copyright notice appear in all copies and that
9: both that copyright notice and this permission notice appear in
10: supporting documentation, and that the name of IBM not be
11: used in advertising or publicity pertaining to distribution of the
12: software without specific, written prior permission.
13:
14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20: SOFTWARE.
21:
22: ******************************************************************/
23:
24: /*
25: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26: */
27: /*
28: * ARGO TP
29: *
30: * $Header: tp_output.c,v 5.4 88/11/18 17:28:08 nhall Exp $
31: * $Source: /usr/argo/sys/netiso/RCS/tp_output.c,v $
32: * %W% (Berkeley) %G% *
33: *
34: * In here is tp_ctloutput(), the guy called by [sg]etsockopt(),
35: */
36:
37: #ifndef lint
38: static char *rcsid = "$Header: tp_output.c,v 5.4 88/11/18 17:28:08 nhall Exp $";
39: #endif lint
40:
41: #include "param.h"
42: #include "systm.h"
43: #include "mbuf.h"
44: #include "protosw.h"
45: #include "socket.h"
46: #include "socketvar.h"
47: #include "errno.h"
48: #include "types.h"
49: #include "time.h"
50: #include "tp_param.h"
51: #include "tp_user.h"
52: #include "tp_stat.h"
53: #include "tp_ip.h"
54: #include "tp_timer.h"
55: #include "argo_debug.h"
56: #include "tp_pcb.h"
57: #include "tp_trace.h"
58:
59: #define USERFLAGSMASK_G 0x0f00643b
60: #define USERFLAGSMASK_S 0x0f000432
61: #define TPDUSIZESHIFT 24
62: #define CLASSHIFT 16
63:
64: /*
65: * NAME: tp_consistency()
66: *
67: * CALLED FROM:
68: * tp_ctloutput(), tp_input()
69: *
70: * FUNCTION and ARGUMENTS:
71: * Checks the consistency of options and tpdusize with class,
72: * using the parameters passed in via (param).
73: * (cmd) may be TP_STRICT or TP_FORCE or both.
74: * Force means it will set all the values in (tpcb) to those in
75: * the input arguements iff no errors were encountered.
76: * Strict means that no inconsistency will be tolerated. If it's
77: * not used, checksum and tpdusize inconsistencies will be tolerated.
78: * The reason for this is that in some cases, when we're negotiating down
79: * from class 4, these options should be changed but should not
80: * cause negotiation to fail.
81: *
82: * RETURNS
83: * E* or EOK
84: * E* if the various parms aren't ok for a given class
85: * EOK if they are ok for a given class
86: */
87:
88: int
89: tp_consistency( tpcb, cmd, param )
90: u_int cmd;
91: struct tp_conn_param *param;
92: struct tp_pcb *tpcb;
93: {
94: register int error = EOK;
95: int class_to_use = tp_mask_to_num(param->p_class);
96:
97: IFTRACE(D_SETPARAMS)
98: tptrace(TPPTmisc,
99: "tp_consist enter class_to_use dontchange param.class cmd",
100: class_to_use, param->p_dont_change_params, param->p_class, cmd);
101: ENDTRACE
102: IFDEBUG(D_SETPARAMS)
103: printf("tp_consistency %s %s\n",
104: cmd& TP_FORCE? "TP_FORCE": "",
105: cmd& TP_STRICT? "TP_STRICT":"");
106: ENDDEBUG
107: if ((cmd & TP_FORCE) && (param->p_dont_change_params)) {
108: cmd &= ~TP_FORCE;
109: }
110: /* can switch net services within a domain, but
111: * cannot switch domains
112: */
113: switch( param->p_netservice) {
114: case ISO_CONS:
115: case ISO_CLNS:
116: case ISO_COSNS:
117: /* param->p_netservice in ISO DOMAIN */
118: if(tpcb->tp_domain != AF_ISO ) {
119: error = EINVAL; goto done;
120: }
121: break;
122: case IN_CLNS:
123: /* param->p_netservice in INET DOMAIN */
124: if( tpcb->tp_domain != AF_INET ) {
125: error = EINVAL; goto done;
126: }
127: break;
128: /* no others not possible-> netservice is a 2-bit field! */
129: }
130:
131: IFDEBUG(D_SETPARAMS)
132: printf("p_class 0x%x, class_to_use 0x%x\n", param->p_class,
133: class_to_use);
134: ENDDEBUG
135: if((param->p_netservice < 0) || (param->p_netservice > TP_MAX_NETSERVICES)){
136: error = EINVAL; goto done;
137: }
138: if( (param->p_class & TP_CLASSES_IMPLEMENTED) == 0 ) {
139: error = EINVAL; goto done;
140: }
141: IFDEBUG(D_SETPARAMS)
142: printf("Nretrans 0x%x\n", param->p_Nretrans );
143: ENDDEBUG
144: if( ( param->p_Nretrans < 1 ) ||
145: (param->p_cr_ticks < 1) || (param->p_cc_ticks < 1) ) {
146: /* bad for any class because negot has to be done a la class 4 */
147: error = EINVAL; goto done;
148: }
149: IFDEBUG(D_SETPARAMS)
150: printf("winsize 0x%x\n", param->p_winsize );
151: ENDDEBUG
152: if( (param->p_winsize < 128 ) ||
153: (param->p_winsize < param->p_tpdusize ) ||
154: (param->p_winsize > ((1+SB_MAX)>>2 /* 1/4 of the max */)) ) {
155: error = EINVAL; goto done;
156: } else {
157: if( tpcb->tp_state == TP_CLOSED )
158: soreserve(tpcb->tp_sock, (u_long)param->p_winsize,
159: (u_long)param->p_winsize);
160: }
161: IFDEBUG(D_SETPARAMS)
162: printf("use_csum 0x%x\n", param->p_use_checksum );
163: printf("xtd_format 0x%x\n", param->p_xtd_format );
164: printf("xpd_service 0x%x\n", param->p_xpd_service );
165: printf("tpdusize 0x%x\n", param->p_tpdusize );
166: printf("tpcb->flags 0x%x\n", tpcb->tp_flags );
167: ENDDEBUG
168: switch( class_to_use ) {
169:
170: case 0:
171: /* do not use checksums, xtd format, or XPD */
172:
173: if( param->p_use_checksum | param->p_xtd_format | param->p_xpd_service ) {
174: if(cmd & TP_STRICT) {
175: error = EINVAL;
176: } else {
177: param->p_use_checksum = 0;
178: param->p_xtd_format = 0;
179: param->p_xpd_service = 0;
180: }
181: break;
182: }
183:
184: if (param->p_tpdusize < TP_MIN_TPDUSIZE) {
185: if(cmd & TP_STRICT) {
186: error = EINVAL;
187: } else {
188: param->p_tpdusize = TP_MIN_TPDUSIZE;
189: }
190: break;
191: }
192: if (param->p_tpdusize > TP0_TPDUSIZE) {
193: if (cmd & TP_STRICT) {
194: error = EINVAL;
195: } else {
196: param->p_tpdusize = TP0_TPDUSIZE;
197: }
198: break;
199: }
200:
201: /* connect/disc data not allowed for class 0 */
202: if (tpcb->tp_ucddata) {
203: if(cmd & TP_STRICT) {
204: error = EINVAL;
205: } else if(cmd & TP_FORCE) {
206: m_freem(tpcb->tp_ucddata);
207: tpcb->tp_ucddata = 0;
208: }
209: }
210: break;
211:
212: case 4:
213: IFDEBUG(D_SETPARAMS)
214: printf("dt_ticks 0x%x\n", param->p_dt_ticks );
215: printf("x_ticks 0x%x\n", param->p_x_ticks );
216: printf("dr_ticks 0x%x\n", param->p_dr_ticks );
217: printf("keepalive 0x%x\n", param->p_keepalive_ticks );
218: printf("sendack 0x%x\n", param->p_sendack_ticks );
219: printf("inact 0x%x\n", param->p_inact_ticks );
220: printf("ref 0x%x\n", param->p_ref_ticks );
221: ENDDEBUG
222: if( (param->p_class & TP_CLASS_4 ) && (
223: (param->p_dt_ticks < 1) || (param->p_dr_ticks < 1) ||
224: (param->p_x_ticks < 1) || (param->p_keepalive_ticks < 1) ||
225: (param->p_sendack_ticks < 1) || (param->p_ref_ticks < 1) ||
226: (param->p_inact_ticks < 1) ) ) {
227: error = EINVAL;
228: break;
229: }
230: IFDEBUG(D_SETPARAMS)
231: printf("rx_strat 0x%x\n", param->p_rx_strat );
232: ENDDEBUG
233: if(param->p_rx_strat >
234: ( TPRX_USE_CW | TPRX_EACH | TPRX_FASTSTART) ) {
235: if(cmd & TP_STRICT) {
236: error = EINVAL;
237: } else {
238: param->p_rx_strat = TPRX_USE_CW;
239: }
240: break;
241: }
242: IFDEBUG(D_SETPARAMS)
243: printf("ack_strat 0x%x\n", param->p_ack_strat );
244: ENDDEBUG
245: if((param->p_ack_strat != 0) && (param->p_ack_strat != 1)) {
246: if(cmd & TP_STRICT) {
247: error = EINVAL;
248: } else {
249: param->p_ack_strat = TPACK_WINDOW;
250: }
251: break;
252: }
253: if (param->p_tpdusize < TP_MIN_TPDUSIZE) {
254: if(cmd & TP_STRICT) {
255: error = EINVAL;
256: } else {
257: param->p_tpdusize = TP_MIN_TPDUSIZE;
258: }
259: break;
260: }
261: if (param->p_tpdusize > TP_TPDUSIZE) {
262: if(cmd & TP_STRICT) {
263: error = EINVAL;
264: } else {
265: param->p_tpdusize = TP_TPDUSIZE;
266: }
267: break;
268: }
269: break;
270: }
271:
272: if ((error==0) && (cmd & TP_FORCE)) {
273: tpcb->tp_tpdusize = param->p_tpdusize;
274: tpcb->tp_class = param->p_class;
275: tpcb->tp_use_checksum = param->p_use_checksum;
276: tpcb->tp_xpd_service = param->p_xpd_service;
277: tpcb->tp_xtd_format = param->p_xtd_format;
278: }
279:
280: done:
281:
282: IFTRACE(D_CONN)
283: tptrace(TPPTmisc, "tp_consist returns class xtdfmt cmd",
284: error, tpcb->tp_class, tpcb->tp_xtd_format, cmd);
285: ENDTRACE
286: IFDEBUG(D_CONN)
287: printf(
288: "tp_consist rtns 0x%x class 0x%x xtd_fmt 0x%x cmd 0x%x\n",
289: error, tpcb->tp_class, tpcb->tp_xtd_format, cmd);
290: ENDDEBUG
291: return error;
292: }
293:
294: /*
295: * NAME: tp_ctloutput()
296: *
297: * CALLED FROM:
298: * [sg]etsockopt(), via so[sg]etopt().
299: *
300: * FUNCTION and ARGUMENTS:
301: * Implements the socket options at transport level.
302: * (cmd) is either PRCO_SETOPT or PRCO_GETOPT (see ../sys/protosw.h).
303: * (so) is the socket.
304: * (level) is SOL_TRANSPORT (see ../sys/socket.h)
305: * (optname) is the particular command or option to be set.
306: * (**mp) is an mbuf structure.
307: *
308: * RETURN VALUE:
309: * ENOTSOCK if the socket hasn't got an associated tpcb
310: * EINVAL if
311: * trying to set window too big
312: * trying to set illegal max tpdu size
313: * trying to set illegal credit fraction
314: * trying to use unknown or unimplemented class of TP
315: * structure passed to set timer values is wrong size
316: * illegal combination of command/GET-SET option,
317: * e.g., GET w/ TPOPT_CDDATA_CLEAR:
318: * EOPNOTSUPP if the level isn't transport, or command is neither GET nor SET
319: * or if the transport-specific command is not implemented
320: * EISCONN if trying a command that isn't allowed after a connection
321: * is established
322: * ENOTCONN if trying a command that is allowed only if a connection is
323: * established
324: * EMSGSIZE if trying to give too much data on connect/disconnect
325: *
326: * SIDE EFFECTS:
327: *
328: * NOTES:
329: */
330: ProtoHook
331: tp_ctloutput(cmd, so, level, optname, mp)
332: int cmd, level, optname;
333: struct socket *so;
334: struct mbuf **mp;
335: {
336: struct tp_pcb *tpcb = sototpcb(so);
337: int s = splnet();
338: caddr_t value;
339: unsigned val_len;
340: int error = 0;
341:
342: IFTRACE(D_REQUEST)
343: tptrace(TPPTmisc, "tp_ctloutput cmd so optname mp",
344: cmd, so, optname, mp);
345: ENDTRACE
346: IFDEBUG(D_REQUEST)
347: printf(
348: "tp_ctloutput so 0x%x cmd 0x%x optname 0x%x, mp 0x%x *mp 0x%x tpcb 0x%x\n",
349: so, cmd, optname, mp, mp?*mp:0, tpcb);
350: ENDDEBUG
351: if( tpcb == (struct tp_pcb *)0 ) {
352: error = ENOTSOCK; goto done;
353: }
354: if(*mp == MNULL) {
355: register struct mbuf *m;
356:
357: MGET(m, M_DONTWAIT, TPMT_SONAME); /* does off, type, next */
358: if (m == NULL) {
359: splx(s);
360: return ENOBUFS;
361: }
362: m->m_len = 0;
363: m->m_act = 0;
364: *mp = m;
365: }
366:
367: /*
368: * Hook so one can set network options via a tp socket.
369: */
370: if ( level == SOL_NETWORK ) {
371: if ((tpcb->tp_nlproto == NULL) || (tpcb->tp_npcb == NULL))
372: error = ENOTSOCK;
373: else if (tpcb->tp_nlproto->nlp_ctloutput == NULL)
374: error = EOPNOTSUPP;
375: else
376: error = (tpcb->tp_nlproto->nlp_ctloutput)(cmd, optname,
377: tpcb->tp_npcb, *mp);
378: goto done;
379: } else if ( level != SOL_TRANSPORT ) {
380: error = EOPNOTSUPP; goto done;
381: }
382: if (cmd != PRCO_GETOPT && cmd != PRCO_SETOPT) {
383: error = EOPNOTSUPP; goto done;
384: }
385: if ( so->so_error ) {
386: error = so->so_error; goto done;
387: }
388:
389: /* The only options allowed after connection is established
390: * are GET (anything) and SET DISC DATA and SET PERF MEAS
391: */
392: if ( ((so->so_state & SS_ISCONNECTING)||(so->so_state & SS_ISCONNECTED))
393: &&
394: (cmd == PRCO_SETOPT &&
395: optname != TPOPT_DISC_DATA &&
396: optname != TPOPT_CFRM_DATA &&
397: optname != TPOPT_PERF_MEAS &&
398: optname != TPOPT_CDDATA_CLEAR ) ) {
399: error = EISCONN; goto done;
400: }
401: /* The only options allowed after disconnection are GET DISC DATA,
402: * and TPOPT_PSTATISTICS
403: * and they're not allowed if the ref timer has gone off, because
404: * the tpcb is gone
405: */
406: if ((so->so_state & (SS_ISCONNECTED | SS_ISCONFIRMING)) == 0) {
407: if ( so->so_tpcb == (caddr_t)0 ) {
408: error = ENOTCONN; goto done;
409: }
410: if ( (tpcb->tp_state == TP_REFWAIT || tpcb->tp_state == TP_CLOSING) &&
411: (optname != TPOPT_DISC_DATA && optname != TPOPT_PSTATISTICS)) {
412: error = ENOTCONN; goto done;
413: }
414: }
415:
416: value = mtod(*mp, caddr_t); /* it's aligned, don't worry,
417: * but lint complains about it
418: */
419: val_len = (*mp)->m_len;
420:
421: switch (optname) {
422:
423: case TPOPT_MY_TSEL:
424: if ( cmd == PRCO_GETOPT ) {
425: ASSERT( tpcb->tp_lsuffixlen <= MAX_TSAP_SEL_LEN );
426: bcopy((caddr_t)tpcb->tp_lsuffix, value, tpcb->tp_lsuffixlen);
427: (*mp)->m_len = tpcb->tp_lsuffixlen;
428: } else /* cmd == PRCO_SETOPT */ {
429: if( (val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0 )) {
430: printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len, (*mp));
431: error = EINVAL;
432: } else {
433: bcopy(value, (caddr_t)tpcb->tp_lsuffix, val_len);
434: tpcb->tp_lsuffixlen = val_len;
435: }
436: }
437: break;
438:
439: case TPOPT_PEER_TSEL:
440: if ( cmd == PRCO_GETOPT ) {
441: ASSERT( tpcb->tp_fsuffixlen <= MAX_TSAP_SEL_LEN );
442: bcopy((caddr_t)tpcb->tp_fsuffix, value, tpcb->tp_fsuffixlen);
443: (*mp)->m_len = tpcb->tp_fsuffixlen;
444: } else /* cmd == PRCO_SETOPT */ {
445: if( (val_len > MAX_TSAP_SEL_LEN) || (val_len <= 0 )) {
446: printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len, (*mp));
447: error = EINVAL;
448: } else {
449: bcopy(value, (caddr_t)tpcb->tp_fsuffix, val_len);
450: tpcb->tp_fsuffixlen = val_len;
451: }
452: }
453: break;
454:
455: case TPOPT_FLAGS:
456: IFDEBUG(D_REQUEST)
457: printf("%s TPOPT_FLAGS value 0x%x *value 0x%x, flags 0x%x \n",
458: cmd==PRCO_GETOPT?"GET":"SET",
459: value,
460: *value,
461: tpcb->tp_flags);
462: ENDDEBUG
463:
464: if ( cmd == PRCO_GETOPT ) {
465: *(int *)value = (int)tpcb->tp_flags;
466: (*mp)->m_len = sizeof(u_int);
467: } else /* cmd == PRCO_SETOPT */ {
468: error = EINVAL; goto done;
469: }
470: break;
471:
472: case TPOPT_PARAMS:
473: /* This handles:
474: * timer values,
475: * class, use of transport expedited data,
476: * max tpdu size, checksum, xtd format and
477: * disconnect indications, and may get rid of connect/disc data
478: */
479: IFDEBUG(D_SETPARAMS)
480: printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value,
481: cmd==PRCO_GETOPT?"GET":"SET");
482: ENDDEBUG
483: IFDEBUG(D_REQUEST)
484: printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value,
485: cmd==PRCO_GETOPT?"GET":"SET");
486: ENDDEBUG
487:
488: if ( cmd == PRCO_GETOPT ) {
489: *(struct tp_conn_param *)value = tpcb->_tp_param;
490: (*mp)->m_len = sizeof(tpcb->_tp_param);
491: } else /* cmd == PRCO_SETOPT */ {
492: if( (error =
493: tp_consistency(tpcb, TP_STRICT | TP_FORCE,
494: (struct tp_conn_param *)value))==0) {
495: /*
496: * tp_consistency doesn't copy the whole set of params
497: */
498: tpcb->_tp_param = *(struct tp_conn_param *)value;
499: (*mp)->m_len = sizeof(tpcb->_tp_param);
500: }
501: }
502: break;
503:
504: case TPOPT_PSTATISTICS:
505: #ifdef TP_PERF_MEAS
506: if (cmd == PRCO_SETOPT) {
507: error = EINVAL; goto done;
508: }
509: IFPERF(tpcb)
510: if (*mp) {
511: struct mbuf * n;
512: do {
513: MFREE(*mp, n);
514: *mp = n;
515: } while (n);
516: }
517: *mp = m_copym(tpcb->tp_p_mbuf, (int)M_COPYALL, M_WAITOK);
518: ENDPERF
519: else {
520: error = EINVAL; goto done;
521: }
522: break;
523: #else
524: error = EOPNOTSUPP;
525: goto done;
526: #endif TP_PERF_MEAS
527:
528: case TPOPT_CDDATA_CLEAR:
529: if (cmd == PRCO_GETOPT) {
530: error = EINVAL;
531: } else {
532: if (tpcb->tp_ucddata) {
533: m_freem(tpcb->tp_ucddata);
534: tpcb->tp_ucddata = 0;
535: }
536: }
537: break;
538:
539: case TPOPT_CFRM_DATA:
540: case TPOPT_DISC_DATA:
541: case TPOPT_CONN_DATA:
542: if( tpcb->tp_class == TP_CLASS_0 ) {
543: error = EOPNOTSUPP;
544: break;
545: }
546: IFDEBUG(D_REQUEST)
547: printf("%s\n", optname==TPOPT_DISC_DATA?"DISC data":"CONN data");
548: printf("m_len 0x%x, vallen 0x%x so_snd.cc 0x%x\n",
549: (*mp)->m_len, val_len, so->so_snd.sb_cc);
550: dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput: sosnd ");
551: ENDDEBUG
552: if (cmd == PRCO_SETOPT) {
553: int len = tpcb->tp_ucddata ? tpcb->tp_ucddata->m_len : 0;
554: /* can append connect data in several calls */
555: if (len + val_len >
556: (optname==TPOPT_CONN_DATA?TP_MAX_CR_DATA:TP_MAX_DR_DATA) ) {
557: error = EMSGSIZE; goto done;
558: }
559: (*mp)->m_next = MNULL;
560: (*mp)->m_act = 0;
561: if (tpcb->tp_ucddata)
562: m_cat(tpcb->tp_ucddata, *mp);
563: else
564: tpcb->tp_ucddata = *mp;
565: IFDEBUG(D_REQUEST)
566: dump_mbuf(tpcb->tp_ucddata, "tp_ctloutput after CONN_DATA");
567: ENDDEBUG
568: IFTRACE(D_REQUEST)
569: tptrace(TPPTmisc,"C/D DATA: flags snd.sbcc val_len",
570: tpcb->tp_flags, so->so_snd.sb_cc,val_len,0);
571: ENDTRACE
572: *mp = MNULL; /* prevent sosetopt from freeing it! */
573: if (optname == TPOPT_CFRM_DATA && (so->so_state & SS_ISCONFIRMING))
574: (void) tp_confirm(tpcb);
575: }
576: break;
577:
578: case TPOPT_PERF_MEAS:
579: #ifdef TP_PERF_MEAS
580: if (cmd == PRCO_GETOPT) {
581: *value = (u_int)tpcb->tp_perf_on;
582: (*mp)->m_len = sizeof(u_int);
583: } else if (cmd == PRCO_SETOPT) {
584: (*mp)->m_len = 0;
585: if ((*value) != 0 && (*value) != 1 )
586: error = EINVAL;
587: else tpcb->tp_perf_on = (*value);
588: }
589: if( tpcb->tp_perf_on )
590: error = tp_setup_perf(tpcb);
591: #else TP_PERF_MEAS
592: error = EOPNOTSUPP;
593: #endif TP_PERF_MEAS
594: break;
595:
596: default:
597: error = EOPNOTSUPP;
598: }
599:
600: done:
601: IFDEBUG(D_REQUEST)
602: dump_mbuf(so->so_snd.sb_mb, "tp_ctloutput sosnd at end");
603: dump_mbuf(*mp, "tp_ctloutput *mp");
604: ENDDEBUG
605: /*
606: * sigh: getsockopt looks only at m_len : all output data must
607: * reside in the first mbuf
608: */
609: if ( error && (*mp) != MNULL )
610: (*mp)->m_len = 0;
611: if( (*mp) != MNULL ) {
612: ASSERT ( m_compress(*mp, mp) <= MLEN );
613: IFDEBUG(D_REQUEST)
614: dump_mbuf(*mp, "tp_ctloutput *mp after compress");
615: ENDDEBUG
616: }
617:
618: splx(s);
619: return error;
620: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.