]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netiso/tp_output.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)tp_output.c 8.1 (Berkeley) 6/10/93
57 /***********************************************************
58 Copyright IBM Corporation 1987
62 Permission to use, copy, modify, and distribute this software and its
63 documentation for any purpose and without fee is hereby granted,
64 provided that the above copyright notice appear in all copies and that
65 both that copyright notice and this permission notice appear in
66 supporting documentation, and that the name of IBM not be
67 used in advertising or publicity pertaining to distribution of the
68 software without specific, written prior permission.
70 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
71 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
72 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
73 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
74 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
75 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
78 ******************************************************************/
81 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
86 * In here is tp_ctloutput(), the guy called by [sg]etsockopt(),
89 #include <sys/param.h>
91 #include <sys/systm.h>
92 #include <sys/socket.h>
93 #include <sys/socketvar.h>
94 #include <sys/protosw.h>
95 #include <sys/errno.h>
97 #include <sys/kernel.h>
99 #include <netiso/tp_param.h>
100 #include <netiso/tp_user.h>
101 #include <netiso/tp_stat.h>
102 #include <netiso/tp_ip.h>
103 #include <netiso/tp_clnp.h>
104 #include <netiso/tp_timer.h>
105 #include <netiso/argo_debug.h>
106 #include <netiso/tp_pcb.h>
107 #include <netiso/tp_trace.h>
109 #define TPDUSIZESHIFT 24
113 * NAME: tp_consistency()
116 * tp_ctloutput(), tp_input()
118 * FUNCTION and ARGUMENTS:
119 * Checks the consistency of options and tpdusize with class,
120 * using the parameters passed in via (param).
121 * (cmd) may be TP_STRICT or TP_FORCE or both.
122 * Force means it will set all the values in (tpcb) to those in
123 * the input arguements iff no errors were encountered.
124 * Strict means that no inconsistency will be tolerated. If it's
125 * not used, checksum and tpdusize inconsistencies will be tolerated.
126 * The reason for this is that in some cases, when we're negotiating down
127 * from class 4, these options should be changed but should not
128 * cause negotiation to fail.
132 * E* if the various parms aren't ok for a given class
133 * EOK if they are ok for a given class
137 tp_consistency( tpcb
, cmd
, param
)
139 struct tp_conn_param
*param
;
142 register int error
= EOK
;
143 int class_to_use
= tp_mask_to_num(param
->p_class
);
147 "tp_consist enter class_to_use dontchange param.class cmd",
148 class_to_use
, param
->p_dont_change_params
, param
->p_class
, cmd
);
151 printf("tp_consistency %s %s\n",
152 cmd
& TP_FORCE
? "TP_FORCE": "",
153 cmd
& TP_STRICT
? "TP_STRICT":"");
155 if ((cmd
& TP_FORCE
) && (param
->p_dont_change_params
)) {
158 /* can switch net services within a domain, but
159 * cannot switch domains
161 switch( param
->p_netservice
) {
165 /* param->p_netservice in ISO DOMAIN */
166 if(tpcb
->tp_domain
!= AF_ISO
) {
167 error
= EINVAL
; goto done
;
171 /* param->p_netservice in INET DOMAIN */
172 if( tpcb
->tp_domain
!= AF_INET
) {
173 error
= EINVAL
; goto done
;
176 /* no others not possible-> netservice is a 2-bit field! */
180 printf("p_class 0x%x, class_to_use 0x%x\n", param
->p_class
,
183 if((param
->p_netservice
< 0) || (param
->p_netservice
> TP_MAX_NETSERVICES
)){
184 error
= EINVAL
; goto done
;
186 if( (param
->p_class
& TP_CLASSES_IMPLEMENTED
) == 0 ) {
187 error
= EINVAL
; goto done
;
190 printf("Nretrans 0x%x\n", param
->p_Nretrans
);
192 if( ( param
->p_Nretrans
< 1 ) ||
193 (param
->p_cr_ticks
< 1) || (param
->p_cc_ticks
< 1) ) {
194 /* bad for any class because negot has to be done a la class 4 */
195 error
= EINVAL
; goto done
;
198 printf("use_csum 0x%x\n", param
->p_use_checksum
);
199 printf("xtd_format 0x%x\n", param
->p_xtd_format
);
200 printf("xpd_service 0x%x\n", param
->p_xpd_service
);
201 printf("tpdusize 0x%x\n", param
->p_tpdusize
);
202 printf("tpcb->flags 0x%x\n", tpcb
->tp_flags
);
204 switch( class_to_use
) {
207 /* do not use checksums, xtd format, or XPD */
209 if( param
->p_use_checksum
| param
->p_xtd_format
| param
->p_xpd_service
) {
210 if(cmd
& TP_STRICT
) {
213 param
->p_use_checksum
= 0;
214 param
->p_xtd_format
= 0;
215 param
->p_xpd_service
= 0;
220 if (param
->p_tpdusize
< TP_MIN_TPDUSIZE
) {
221 if(cmd
& TP_STRICT
) {
224 param
->p_tpdusize
= TP_MIN_TPDUSIZE
;
228 if (param
->p_tpdusize
> TP0_TPDUSIZE
) {
229 if (cmd
& TP_STRICT
) {
232 param
->p_tpdusize
= TP0_TPDUSIZE
;
237 /* connect/disc data not allowed for class 0 */
238 if (tpcb
->tp_ucddata
) {
239 if(cmd
& TP_STRICT
) {
241 } else if(cmd
& TP_FORCE
) {
242 m_freem(tpcb
->tp_ucddata
);
243 tpcb
->tp_ucddata
= 0;
250 printf("dt_ticks 0x%x\n", param
->p_dt_ticks
);
251 printf("x_ticks 0x%x\n", param
->p_x_ticks
);
252 printf("dr_ticks 0x%x\n", param
->p_dr_ticks
);
253 printf("keepalive 0x%x\n", param
->p_keepalive_ticks
);
254 printf("sendack 0x%x\n", param
->p_sendack_ticks
);
255 printf("inact 0x%x\n", param
->p_inact_ticks
);
256 printf("ref 0x%x\n", param
->p_ref_ticks
);
258 if( (param
->p_class
& TP_CLASS_4
) && (
259 (param
->p_dt_ticks
< 1) || (param
->p_dr_ticks
< 1) ||
260 (param
->p_x_ticks
< 1) || (param
->p_keepalive_ticks
< 1) ||
261 (param
->p_sendack_ticks
< 1) || (param
->p_ref_ticks
< 1) ||
262 (param
->p_inact_ticks
< 1) ) ) {
267 printf("rx_strat 0x%x\n", param
->p_rx_strat
);
269 if(param
->p_rx_strat
>
270 ( TPRX_USE_CW
| TPRX_EACH
| TPRX_FASTSTART
) ) {
271 if(cmd
& TP_STRICT
) {
274 param
->p_rx_strat
= TPRX_USE_CW
;
279 printf("ack_strat 0x%x\n", param
->p_ack_strat
);
281 if((param
->p_ack_strat
!= 0) && (param
->p_ack_strat
!= 1)) {
282 if(cmd
& TP_STRICT
) {
285 param
->p_ack_strat
= TPACK_WINDOW
;
289 if (param
->p_tpdusize
< TP_MIN_TPDUSIZE
) {
290 if(cmd
& TP_STRICT
) {
293 param
->p_tpdusize
= TP_MIN_TPDUSIZE
;
297 if (param
->p_tpdusize
> TP_TPDUSIZE
) {
298 if(cmd
& TP_STRICT
) {
301 param
->p_tpdusize
= TP_TPDUSIZE
;
308 if ((error
==0) && (cmd
& TP_FORCE
)) {
309 long dusize
= ((long)param
->p_ptpdusize
) << 7;
310 /* Enforce Negotation rules below */
311 tpcb
->tp_class
= param
->p_class
;
312 if (tpcb
->tp_use_checksum
|| param
->p_use_checksum
)
313 tpcb
->tp_use_checksum
= 1;
314 if (!tpcb
->tp_xpd_service
|| !param
->p_xpd_service
)
315 tpcb
->tp_xpd_service
= 0;
316 if (!tpcb
->tp_xtd_format
|| !param
->p_xtd_format
)
317 tpcb
->tp_xtd_format
= 0;
319 if (tpcb
->tp_l_tpdusize
> dusize
)
320 tpcb
->tp_l_tpdusize
= dusize
;
321 if (tpcb
->tp_ptpdusize
== 0 ||
322 tpcb
->tp_ptpdusize
> param
->p_ptpdusize
)
323 tpcb
->tp_ptpdusize
= param
->p_ptpdusize
;
325 if (param
->p_tpdusize
!= 0 &&
326 tpcb
->tp_tpdusize
> param
->p_tpdusize
)
327 tpcb
->tp_tpdusize
= param
->p_tpdusize
;
328 tpcb
->tp_l_tpdusize
= 1 << tpcb
->tp_tpdusize
;
334 tptrace(TPPTmisc
, "tp_consist returns class xtdfmt cmd",
335 error
, tpcb
->tp_class
, tpcb
->tp_xtd_format
, cmd
);
339 "tp_consist rtns 0x%x class 0x%x xtd_fmt 0x%x cmd 0x%x\n",
340 error
, tpcb
->tp_class
, tpcb
->tp_xtd_format
, cmd
);
346 * NAME: tp_ctloutput()
349 * [sg]etsockopt(), via so[sg]etopt().
351 * FUNCTION and ARGUMENTS:
352 * Implements the socket options at transport level.
353 * (cmd) is either PRCO_SETOPT or PRCO_GETOPT (see ../sys/protosw.h).
354 * (so) is the socket.
355 * (level) is SOL_TRANSPORT (see ../sys/socket.h)
356 * (optname) is the particular command or option to be set.
357 * (**mp) is an mbuf structure.
360 * ENOTSOCK if the socket hasn't got an associated tpcb
362 * trying to set window too big
363 * trying to set illegal max tpdu size
364 * trying to set illegal credit fraction
365 * trying to use unknown or unimplemented class of TP
366 * structure passed to set timer values is wrong size
367 * illegal combination of command/GET-SET option,
368 * e.g., GET w/ TPOPT_CDDATA_CLEAR:
369 * EOPNOTSUPP if the level isn't transport, or command is neither GET nor SET
370 * or if the transport-specific command is not implemented
371 * EISCONN if trying a command that isn't allowed after a connection
373 * ENOTCONN if trying a command that is allowed only if a connection is
375 * EMSGSIZE if trying to give too much data on connect/disconnect
382 tp_ctloutput(cmd
, so
, level
, optname
, mp
)
383 int cmd
, level
, optname
;
387 struct tp_pcb
*tpcb
= sototpcb(so
);
394 tptrace(TPPTmisc
, "tp_ctloutput cmd so optname mp",
395 cmd
, so
, optname
, mp
);
399 "tp_ctloutput so 0x%x cmd 0x%x optname 0x%x, mp 0x%x *mp 0x%x tpcb 0x%x\n",
400 so
, cmd
, optname
, mp
, mp
?*mp
:0, tpcb
);
402 if( tpcb
== (struct tp_pcb
*)0 ) {
403 error
= ENOTSOCK
; goto done
;
406 register struct mbuf
*m
;
408 MGET(m
, M_DONTWAIT
, TPMT_SONAME
); /* does off, type, next */
419 * Hook so one can set network options via a tp socket.
421 if ( level
== SOL_NETWORK
) {
422 if ((tpcb
->tp_nlproto
== NULL
) || (tpcb
->tp_npcb
== NULL
))
424 else if (tpcb
->tp_nlproto
->nlp_ctloutput
== NULL
)
427 return ((tpcb
->tp_nlproto
->nlp_ctloutput
)(cmd
, optname
,
428 tpcb
->tp_npcb
, *mp
));
430 } else if ( level
== SOL_SOCKET
) {
431 if (optname
== SO_RCVBUF
&& cmd
== PRCO_SETOPT
) {
432 u_long old_credit
= tpcb
->tp_maxlcredit
;
434 if (tpcb
->tp_rhiwat
!= so
->so_rcv
.sb_hiwat
&&
435 tpcb
->tp_state
== TP_OPEN
&&
436 (old_credit
< tpcb
->tp_maxlcredit
))
437 tp_emit(AK_TPDU_type
, tpcb
,
438 tpcb
->tp_rcvnxt
, 0, MNULL
);
439 tpcb
->tp_rhiwat
= so
->so_rcv
.sb_hiwat
;
442 } else if ( level
!= SOL_TRANSPORT
) {
443 error
= EOPNOTSUPP
; goto done
;
445 if (cmd
!= PRCO_GETOPT
&& cmd
!= PRCO_SETOPT
) {
446 error
= EOPNOTSUPP
; goto done
;
448 if ( so
->so_error
) {
449 error
= so
->so_error
; goto done
;
452 /* The only options allowed after connection is established
453 * are GET (anything) and SET DISC DATA and SET PERF MEAS
455 if ( ((so
->so_state
& SS_ISCONNECTING
)||(so
->so_state
& SS_ISCONNECTED
))
457 (cmd
== PRCO_SETOPT
&&
458 optname
!= TPOPT_DISC_DATA
&&
459 optname
!= TPOPT_CFRM_DATA
&&
460 optname
!= TPOPT_PERF_MEAS
&&
461 optname
!= TPOPT_CDDATA_CLEAR
) ) {
462 error
= EISCONN
; goto done
;
464 /* The only options allowed after disconnection are GET DISC DATA,
465 * and TPOPT_PSTATISTICS
466 * and they're not allowed if the ref timer has gone off, because
469 if ((so
->so_state
& (SS_ISCONNECTED
| SS_ISCONFIRMING
)) == 0) {
470 if ( so
->so_pcb
== (caddr_t
)0 ) {
471 error
= ENOTCONN
; goto done
;
473 if ( (tpcb
->tp_state
== TP_REFWAIT
|| tpcb
->tp_state
== TP_CLOSING
) &&
474 (optname
!= TPOPT_DISC_DATA
&& optname
!= TPOPT_PSTATISTICS
)) {
475 error
= ENOTCONN
; goto done
;
479 value
= mtod(*mp
, caddr_t
); /* it's aligned, don't worry,
480 * but lint complains about it
482 val_len
= (*mp
)->m_len
;
486 case TPOPT_INTERCEPT
:
487 #define INA(t) (((struct inpcb *)(t->tp_npcb))->inp_laddr.s_addr)
488 #define ISOA(t) (((struct isopcb *)(t->tp_npcb))->isop_laddr->siso_addr)
490 if ((so
->so_state
& SS_PRIV
) == 0) {
492 } else if (cmd
!= PRCO_SETOPT
|| tpcb
->tp_state
!= TP_CLOSED
||
493 (tpcb
->tp_flags
& TPF_GENERAL_ADDR
) ||
497 register struct tp_pcb
*t
;
499 for (t
= tp_listeners
; t
; t
= t
->tp_nextlisten
)
500 if ((t
->tp_flags
& TPF_GENERAL_ADDR
) == 0 &&
501 t
->tp_domain
== tpcb
->tp_domain
)
502 switch (tpcb
->tp_domain
) {
507 if (INA(t
) == INA(tpcb
))
513 if (bcmp(ISOA(t
).isoa_genaddr
, ISOA(tpcb
).isoa_genaddr
,
514 ISOA(t
).isoa_len
) == 0)
519 tpcb
->tp_lsuffixlen
= 0;
520 tpcb
->tp_state
= TP_LISTENING
;
523 tpcb
->tp_next
= tpcb
->tp_prev
= tpcb
;
524 tpcb
->tp_nextlisten
= tp_listeners
;
530 if ( cmd
== PRCO_GETOPT
) {
531 ASSERT( tpcb
->tp_lsuffixlen
<= MAX_TSAP_SEL_LEN
);
532 bcopy((caddr_t
)tpcb
->tp_lsuffix
, value
, tpcb
->tp_lsuffixlen
);
533 (*mp
)->m_len
= tpcb
->tp_lsuffixlen
;
534 } else /* cmd == PRCO_SETOPT */ {
535 if( (val_len
> MAX_TSAP_SEL_LEN
) || (val_len
<= 0 )) {
536 printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len
, (*mp
));
539 bcopy(value
, (caddr_t
)tpcb
->tp_lsuffix
, val_len
);
540 tpcb
->tp_lsuffixlen
= val_len
;
545 case TPOPT_PEER_TSEL
:
546 if ( cmd
== PRCO_GETOPT
) {
547 ASSERT( tpcb
->tp_fsuffixlen
<= MAX_TSAP_SEL_LEN
);
548 bcopy((caddr_t
)tpcb
->tp_fsuffix
, value
, tpcb
->tp_fsuffixlen
);
549 (*mp
)->m_len
= tpcb
->tp_fsuffixlen
;
550 } else /* cmd == PRCO_SETOPT */ {
551 if( (val_len
> MAX_TSAP_SEL_LEN
) || (val_len
<= 0 )) {
552 printf("val_len 0x%x (*mp)->m_len 0x%x\n", val_len
, (*mp
));
555 bcopy(value
, (caddr_t
)tpcb
->tp_fsuffix
, val_len
);
556 tpcb
->tp_fsuffixlen
= val_len
;
563 printf("%s TPOPT_FLAGS value 0x%x *value 0x%x, flags 0x%x \n",
564 cmd
==PRCO_GETOPT
?"GET":"SET",
570 if ( cmd
== PRCO_GETOPT
) {
571 *(int *)value
= (int)tpcb
->tp_flags
;
572 (*mp
)->m_len
= sizeof(u_int
);
573 } else /* cmd == PRCO_SETOPT */ {
574 error
= EINVAL
; goto done
;
581 * class, use of transport expedited data,
582 * max tpdu size, checksum, xtd format and
583 * disconnect indications, and may get rid of connect/disc data
586 printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value
,
587 cmd
==PRCO_GETOPT
?"GET":"SET");
590 printf("TPOPT_PARAMS value 0x%x, cmd %s \n", value
,
591 cmd
==PRCO_GETOPT
?"GET":"SET");
594 if ( cmd
== PRCO_GETOPT
) {
595 *(struct tp_conn_param
*)value
= tpcb
->_tp_param
;
596 (*mp
)->m_len
= sizeof(tpcb
->_tp_param
);
597 } else /* cmd == PRCO_SETOPT */ {
599 tp_consistency(tpcb
, TP_STRICT
| TP_FORCE
,
600 (struct tp_conn_param
*)value
))==0) {
602 * tp_consistency doesn't copy the whole set of params
604 tpcb
->_tp_param
= *(struct tp_conn_param
*)value
;
605 (*mp
)->m_len
= sizeof(tpcb
->_tp_param
);
610 case TPOPT_PSTATISTICS
:
612 if (cmd
== PRCO_SETOPT
) {
613 error
= EINVAL
; goto done
;
623 *mp
= m_copym(tpcb
->tp_p_mbuf
, (int)M_COPYALL
, M_WAITOK
);
626 error
= EINVAL
; goto done
;
632 #endif /* TP_PERF_MEAS */
634 case TPOPT_CDDATA_CLEAR
:
635 if (cmd
== PRCO_GETOPT
) {
638 if (tpcb
->tp_ucddata
) {
639 m_freem(tpcb
->tp_ucddata
);
640 tpcb
->tp_ucddata
= 0;
645 case TPOPT_CFRM_DATA
:
646 case TPOPT_DISC_DATA
:
647 case TPOPT_CONN_DATA
:
648 if( tpcb
->tp_class
== TP_CLASS_0
) {
653 printf("%s\n", optname
==TPOPT_DISC_DATA
?"DISC data":"CONN data");
654 printf("m_len 0x%x, vallen 0x%x so_snd.cc 0x%x\n",
655 (*mp
)->m_len
, val_len
, so
->so_snd
.sb_cc
);
656 dump_mbuf(so
->so_snd
.sb_mb
, "tp_ctloutput: sosnd ");
658 if (cmd
== PRCO_SETOPT
) {
659 int len
= tpcb
->tp_ucddata
? tpcb
->tp_ucddata
->m_len
: 0;
660 /* can append connect data in several calls */
662 (optname
==TPOPT_CONN_DATA
?TP_MAX_CR_DATA
:TP_MAX_DR_DATA
) ) {
663 error
= EMSGSIZE
; goto done
;
665 (*mp
)->m_next
= MNULL
;
667 if (tpcb
->tp_ucddata
)
668 m_cat(tpcb
->tp_ucddata
, *mp
);
670 tpcb
->tp_ucddata
= *mp
;
672 dump_mbuf(tpcb
->tp_ucddata
, "tp_ctloutput after CONN_DATA");
675 tptrace(TPPTmisc
,"C/D DATA: flags snd.sbcc val_len",
676 tpcb
->tp_flags
, so
->so_snd
.sb_cc
,val_len
,0);
679 if (optname
== TPOPT_CFRM_DATA
&& (so
->so_state
& SS_ISCONFIRMING
))
680 (void) tp_confirm(tpcb
);
684 case TPOPT_PERF_MEAS
:
686 if (cmd
== PRCO_GETOPT
) {
687 *value
= (u_int
)tpcb
->tp_perf_on
;
688 (*mp
)->m_len
= sizeof(u_int
);
689 } else if (cmd
== PRCO_SETOPT
) {
691 if ((*value
) != 0 && (*value
) != 1 )
693 else tpcb
->tp_perf_on
= (*value
);
695 if( tpcb
->tp_perf_on
)
696 error
= tp_setup_perf(tpcb
);
697 #else /* TP_PERF_MEAS */
699 #endif /* TP_PERF_MEAS */
708 dump_mbuf(so
->so_snd
.sb_mb
, "tp_ctloutput sosnd at end");
709 dump_mbuf(*mp
, "tp_ctloutput *mp");
712 * sigh: getsockopt looks only at m_len : all output data must
713 * reside in the first mbuf
716 if (cmd
== PRCO_SETOPT
) {
720 ASSERT ( m_compress(*mp
, mp
) <= MLEN
);
724 dump_mbuf(*mp
, "tp_ctloutput *mp after compress");