2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* The rxkad security object. Routines used by both client and servers. */
12 #include <afsconfig.h>
13 #include <afs/param.h>
17 #include <sys/time_impl.h>
20 #define INCLUDE_RXKAD_PRIVATE_DECLS
24 #include "afs/afs_osi.h"
25 #if defined(AFS_AIX_ENV) || defined(AFS_AUX_ENV) || defined(AFS_SUN5_ENV)
28 #if defined(AFS_DARWIN_ENV) || defined(AFS_OBSD_ENV)
34 #include "afs/sysincludes.h"
35 #include "afsincludes.h"
40 #if defined(AFS_NT40_ENV) && defined(AFS_PTHREAD_ENV)
41 #define RXKAD_STATS_DECLSPEC __declspec(dllexport)
46 #include <rx/rx_packet.h>
50 #include "private_data.h"
51 #define XPRT_RXKAD_COMMON
54 #define afs_max(a,b) ((a) < (b)? (b) : (a))
58 #define osi_Time() time(0)
60 /* variable initialization for the benefit of darwin compiler; if it causes
61 problems elsewhere, conditionalize for darwin or fc_test compile breaks */
62 #if defined(AFS_PTHREAD_ENV) && !defined(KERNEL)
63 struct rxkad_global_stats rxkad_global_stats
;
64 pthread_mutex_t rxkad_global_stats_lock
;
65 pthread_key_t rxkad_stats_key
;
66 #else /* AFS_PTHREAD_ENV && !KERNEL */
67 struct rxkad_stats rxkad_stats
;
68 #endif /* AFS_PTHREAD_ENV && !KERNEL */
70 #if defined(AFS_PTHREAD_ENV) && !defined(KERNEL)
71 /* Pthread initialisation */
72 static pthread_once_t rxkad_once_init
= PTHREAD_ONCE_INIT
;
73 extern pthread_mutex_t rxkad_random_mutex
;
76 rxkad_global_stats_init(void)
78 osi_Assert(pthread_mutex_init(&rxkad_global_stats_lock
, (const pthread_mutexattr_t
*)0) == 0);
79 osi_Assert(pthread_key_create(&rxkad_stats_key
, NULL
) == 0);
80 memset(&rxkad_global_stats
, 0, sizeof(rxkad_global_stats
));
84 rxkad_InitPthread(void) {
85 MUTEX_INIT(&rxkad_random_mutex
, "rxkad random", MUTEX_DEFAULT
, 0);
87 rxkad_global_stats_init();
92 osi_Assert(pthread_once(&rxkad_once_init
, rxkad_InitPthread
) == 0);
95 /* rxkad_stats related stuff */
98 * Macro to insert an element at the tail of a doubly linked list
100 #define DLL_INSERT_TAIL(ptr,head,tail,next,prev) \
102 (ptr)->next = NULL; \
103 (ptr)->prev = (tail); \
106 (ptr)->prev->next = (ptr); \
109 osi_Assert((head) && ((head)->prev == NULL)); \
113 rxkad_thr_stats_init(void) {
114 rxkad_stats_t
* rxkad_stats
;
115 rxkad_stats
= calloc(1, sizeof(rxkad_stats_t
));
116 osi_Assert(rxkad_stats
!= NULL
&& pthread_setspecific(rxkad_stats_key
,rxkad_stats
) == 0);
117 RXKAD_GLOBAL_STATS_LOCK
;
118 DLL_INSERT_TAIL(rxkad_stats
, rxkad_global_stats
.first
, rxkad_global_stats
.last
, next
, prev
);
119 RXKAD_GLOBAL_STATS_UNLOCK
;
123 int rxkad_stats_agg(rxkad_stats_t
* rxkad_stats
) {
124 rxkad_stats_t
* thr_stats
;
125 osi_Assert(rxkad_stats
!= NULL
);
126 memset(rxkad_stats
, 0, sizeof(rxkad_stats_t
));
127 RXKAD_GLOBAL_STATS_LOCK
;
128 for (thr_stats
= rxkad_global_stats
.first
; thr_stats
!= NULL
; thr_stats
= thr_stats
->next
) {
129 rxkad_stats
->connections
[0] += thr_stats
->connections
[0];
130 rxkad_stats
->connections
[1] += thr_stats
->connections
[1];
131 rxkad_stats
->connections
[2] += thr_stats
->connections
[2];
132 rxkad_stats
->destroyObject
+= thr_stats
->destroyObject
;
133 rxkad_stats
->destroyClient
+= thr_stats
->destroyClient
;
134 rxkad_stats
->destroyUnused
+= thr_stats
->destroyUnused
;
135 rxkad_stats
->destroyUnauth
+= thr_stats
->destroyUnauth
;
136 rxkad_stats
->destroyConn
[0] += thr_stats
->destroyConn
[0];
137 rxkad_stats
->destroyConn
[1] += thr_stats
->destroyConn
[1];
138 rxkad_stats
->destroyConn
[2] += thr_stats
->destroyConn
[2];
139 rxkad_stats
->expired
+= thr_stats
->expired
;
140 rxkad_stats
->challengesSent
+= thr_stats
->challengesSent
;
141 rxkad_stats
->challenges
[0] += thr_stats
->challenges
[0];
142 rxkad_stats
->challenges
[1] += thr_stats
->challenges
[1];
143 rxkad_stats
->challenges
[2] += thr_stats
->challenges
[2];
144 rxkad_stats
->responses
[0] += thr_stats
->responses
[0];
145 rxkad_stats
->responses
[1] += thr_stats
->responses
[1];
146 rxkad_stats
->responses
[2] += thr_stats
->responses
[2];
147 rxkad_stats
->preparePackets
[0] += thr_stats
->preparePackets
[0];
148 rxkad_stats
->preparePackets
[1] += thr_stats
->preparePackets
[1];
149 rxkad_stats
->preparePackets
[2] += thr_stats
->preparePackets
[2];
150 rxkad_stats
->preparePackets
[3] += thr_stats
->preparePackets
[3];
151 rxkad_stats
->preparePackets
[4] += thr_stats
->preparePackets
[4];
152 rxkad_stats
->preparePackets
[5] += thr_stats
->preparePackets
[5];
153 rxkad_stats
->checkPackets
[0] += thr_stats
->checkPackets
[0];
154 rxkad_stats
->checkPackets
[1] += thr_stats
->checkPackets
[1];
155 rxkad_stats
->checkPackets
[2] += thr_stats
->checkPackets
[2];
156 rxkad_stats
->checkPackets
[3] += thr_stats
->checkPackets
[3];
157 rxkad_stats
->checkPackets
[4] += thr_stats
->checkPackets
[4];
158 rxkad_stats
->checkPackets
[5] += thr_stats
->checkPackets
[5];
159 rxkad_stats
->bytesEncrypted
[0] += thr_stats
->bytesEncrypted
[0];
160 rxkad_stats
->bytesEncrypted
[1] += thr_stats
->bytesEncrypted
[1];
161 rxkad_stats
->bytesDecrypted
[0] += thr_stats
->bytesDecrypted
[0];
162 rxkad_stats
->bytesDecrypted
[1] += thr_stats
->bytesDecrypted
[1];
163 rxkad_stats
->fc_encrypts
[0] += thr_stats
->fc_encrypts
[0];
164 rxkad_stats
->fc_encrypts
[1] += thr_stats
->fc_encrypts
[1];
165 rxkad_stats
->fc_key_scheds
+= thr_stats
->fc_key_scheds
;
166 rxkad_stats
->des_encrypts
[0] += thr_stats
->des_encrypts
[0];
167 rxkad_stats
->des_encrypts
[1] += thr_stats
->des_encrypts
[1];
168 rxkad_stats
->des_key_scheds
+= thr_stats
->des_key_scheds
;
169 rxkad_stats
->des_randoms
+= thr_stats
->des_randoms
;
170 rxkad_stats
->clientObjects
+= thr_stats
->clientObjects
;
171 rxkad_stats
->serverObjects
+= thr_stats
->serverObjects
;
172 rxkad_stats
->spares
[0] += thr_stats
->spares
[0];
173 rxkad_stats
->spares
[1] += thr_stats
->spares
[1];
174 rxkad_stats
->spares
[2] += thr_stats
->spares
[2];
175 rxkad_stats
->spares
[3] += thr_stats
->spares
[3];
176 rxkad_stats
->spares
[4] += thr_stats
->spares
[4];
177 rxkad_stats
->spares
[5] += thr_stats
->spares
[5];
178 rxkad_stats
->spares
[6] += thr_stats
->spares
[6];
179 rxkad_stats
->spares
[7] += thr_stats
->spares
[7];
181 RXKAD_GLOBAL_STATS_UNLOCK
;
184 #else /* AFS_PTHREAD_ENV && !KERNEL */
190 #endif /* AFS_PTHREAD_ENV && !KERNEL */
192 /* static prototypes */
193 static afs_int32
ComputeSum(struct rx_packet
*apacket
,
194 fc_KeySchedule
* aschedule
, afs_int32
* aivec
);
195 static afs_int32
FreeObject(struct rx_securityClass
*aobj
);
197 /* this call sets up an endpoint structure, leaving it in *network* byte
198 * order so that it can be used quickly for encryption.
201 rxkad_SetupEndpoint(struct rx_connection
*aconnp
,
202 struct rxkad_endpoint
*aendpointp
)
206 aendpointp
->cuid
[0] = htonl(rx_GetConnectionEpoch(aconnp
));
207 i
= rx_GetConnectionId(aconnp
) & RX_CIDMASK
;
208 aendpointp
->cuid
[1] = htonl(i
);
209 aendpointp
->cksum
= 0; /* used as cksum only in chal resp. */
210 aendpointp
->securityIndex
= htonl(rx_SecurityClassOf(aconnp
));
214 /* setup xor information based on session key */
216 rxkad_DeriveXORInfo(struct rx_connection
*aconnp
, fc_KeySchedule
* aschedule
,
217 char *aivec
, char *aresult
)
219 struct rxkad_endpoint tendpoint
;
222 rxkad_SetupEndpoint(aconnp
, &tendpoint
);
223 memcpy((void *)xor, aivec
, 2 * sizeof(afs_int32
));
224 fc_cbc_encrypt(&tendpoint
, &tendpoint
, sizeof(tendpoint
), *aschedule
, xor,
227 ((char *)&tendpoint
) + sizeof(tendpoint
) - ENCRYPTIONBLOCKSIZE
,
228 ENCRYPTIONBLOCKSIZE
);
232 /* rxkad_CksumChallengeResponse - computes a checksum of the components of a
233 * challenge response packet (which must be unencrypted and in network order).
234 * The endpoint.cksum field is omitted and treated as zero. The cksum is
235 * returned in network order. */
238 rxkad_CksumChallengeResponse(struct rxkad_v2ChallengeResponse
* v2r
)
242 u_char
*cp
= (u_char
*) v2r
;
243 afs_uint32 savedCksum
= v2r
->encrypted
.endpoint
.cksum
;
245 v2r
->encrypted
.endpoint
.cksum
= 0;
247 /* this function captured from budb/db_hash.c */
249 for (i
= 0; i
< sizeof(*v2r
); i
++)
250 cksum
= (*cp
++) + cksum
* 0x10204081;
252 v2r
->encrypted
.endpoint
.cksum
= savedCksum
;
257 rxkad_SetLevel(struct rx_connection
*conn
, rxkad_level level
)
259 if (level
== rxkad_auth
) {
260 rx_SetSecurityHeaderSize(conn
, 4);
261 rx_SetSecurityMaxTrailerSize(conn
, 4);
262 } else if (level
== rxkad_crypt
) {
263 rx_SetSecurityHeaderSize(conn
, 8);
264 rx_SetSecurityMaxTrailerSize(conn
, 8); /* XXX was 7, but why screw with
265 * unaligned accesses? */
269 /* returns a short integer in host byte order representing a good checksum of
273 ComputeSum(struct rx_packet
*apacket
, fc_KeySchedule
* aschedule
,
279 t
= apacket
->header
.callNumber
;
281 /* note that word [1] includes the channel # */
282 t
= ((apacket
->header
.cid
& 0x3) << 30)
283 | ((apacket
->header
.seq
& 0x3fffffff));
285 /* XOR in the ivec from the per-endpoint encryption */
288 /* encrypts word as if it were a character string */
289 fc_ecb_encrypt(word
, word
, *aschedule
, ENCRYPT
);
291 t
= (t
>> 16) & 0xffff;
293 t
= 1; /* so that 0 means don't care */
299 FreeObject(struct rx_securityClass
*aobj
)
301 struct rxkad_cprivate
*tcp
; /* both structs start w/ type field */
303 if (aobj
->refCount
> 0)
304 return 0; /* still in use */
305 tcp
= (struct rxkad_cprivate
*)aobj
->privateData
;
306 rxi_Free(aobj
, sizeof(struct rx_securityClass
));
307 if (tcp
->type
& rxkad_client
) {
308 afs_int32 psize
= PDATA_SIZE(tcp
->ticketLen
);
309 rxi_Free(tcp
, psize
);
310 } else if (tcp
->type
& rxkad_server
) {
311 rxi_Free(tcp
, sizeof(struct rxkad_sprivate
));
313 return RXKADINCONSISTENCY
;
315 INC_RXKAD_STATS(destroyObject
);
319 /* rxkad_Close - called by rx with the security class object as a parameter
320 * when a security object is to be discarded */
323 rxkad_Close(struct rx_securityClass
*aobj
)
327 code
= FreeObject(aobj
);
331 /* either: called to (re)create a new connection. */
334 rxkad_NewConnection(struct rx_securityClass
*aobj
,
335 struct rx_connection
*aconn
)
337 if (rx_GetSecurityData(aconn
) != NULL
)
338 return RXKADINCONSISTENCY
; /* already allocated??? */
340 if (rx_IsServerConn(aconn
)) {
341 struct rxkad_sconn
*data
;
342 data
= rxi_Alloc(sizeof(struct rxkad_sconn
));
343 memset(data
, 0, sizeof(struct rxkad_sconn
));
344 rx_SetSecurityData(aconn
, data
);
345 } else { /* client */
346 struct rxkad_cprivate
*tcp
;
347 struct rxkad_cconn
*data
;
349 data
= rxi_Alloc(sizeof(struct rxkad_cconn
));
350 memset(data
, 0, sizeof(struct rxkad_cconn
));
351 rx_SetSecurityData(aconn
, data
);
353 tcp
= (struct rxkad_cprivate
*)aobj
->privateData
;
354 if (!(tcp
->type
& rxkad_client
))
355 return RXKADINCONSISTENCY
;
356 rxkad_SetLevel(aconn
, tcp
->level
); /* set header and trailer sizes */
357 rxkad_DeriveXORInfo(aconn
, (fc_KeySchedule
*)tcp
->keysched
, (char *)tcp
->ivec
, (char *)data
->preSeq
);
358 INC_RXKAD_STATS(connections
[rxkad_LevelIndex(tcp
->level
)]);
361 aobj
->refCount
++; /* attached connection */
365 /* either: called to destroy a connection. */
368 rxkad_DestroyConnection(struct rx_securityClass
*aobj
,
369 struct rx_connection
*aconn
)
371 if (rx_IsServerConn(aconn
)) {
372 struct rxkad_sconn
*sconn
;
373 struct rxkad_serverinfo
*rock
;
374 sconn
= rx_GetSecurityData(aconn
);
376 rx_SetSecurityData(aconn
, NULL
);
377 if (sconn
->authenticated
)
378 INC_RXKAD_STATS(destroyConn
[rxkad_LevelIndex(sconn
->level
)]);
380 INC_RXKAD_STATS(destroyUnauth
);
383 rxi_Free(rock
, sizeof(struct rxkad_serverinfo
));
384 rxi_Free(sconn
, sizeof(struct rxkad_sconn
));
386 INC_RXKAD_STATS(destroyUnused
);
388 } else { /* client */
389 struct rxkad_cconn
*cconn
;
390 struct rxkad_cprivate
*tcp
;
391 cconn
= rx_GetSecurityData(aconn
);
392 tcp
= (struct rxkad_cprivate
*)aobj
->privateData
;
393 if (!(tcp
->type
& rxkad_client
))
394 return RXKADINCONSISTENCY
;
396 rx_SetSecurityData(aconn
, NULL
);
397 rxi_Free(cconn
, sizeof(struct rxkad_cconn
));
399 INC_RXKAD_STATS(destroyClient
);
401 aobj
->refCount
--; /* decrement connection counter */
402 if (aobj
->refCount
<= 0) {
404 code
= FreeObject(aobj
);
411 /* either: decode packet */
414 rxkad_CheckPacket(struct rx_securityClass
*aobj
, struct rx_call
*acall
,
415 struct rx_packet
*apacket
)
417 struct rx_connection
*tconn
;
419 const fc_KeySchedule
*schedule
;
420 fc_InitializationVector
*ivec
;
423 u_int word
; /* so we get unsigned right-shift */
428 tconn
= rx_ConnectionOf(acall
);
429 len
= rx_GetDataSize(apacket
);
430 if (rx_IsServerConn(tconn
)) {
431 struct rxkad_sconn
*sconn
;
432 sconn
= rx_GetSecurityData(tconn
);
433 if (rx_GetPacketCksum(apacket
) != 0)
434 sconn
->cksumSeen
= 1;
435 checkCksum
= sconn
->cksumSeen
;
436 if (sconn
&& sconn
->authenticated
437 && (osi_Time() < sconn
->expirationTime
)) {
438 level
= sconn
->level
;
439 INC_RXKAD_STATS(checkPackets
[rxkad_StatIndex(rxkad_server
, level
)]);
440 sconn
->stats
.packetsReceived
++;
441 sconn
->stats
.bytesReceived
+= len
;
442 schedule
= (const fc_KeySchedule
*) sconn
->keysched
;
443 ivec
= (fc_InitializationVector
*) sconn
->ivec
;
445 INC_RXKAD_STATS(expired
);
448 preSeq
= sconn
->preSeq
;
449 } else { /* client connection */
450 struct rxkad_cconn
*cconn
;
451 struct rxkad_cprivate
*tcp
;
452 cconn
= rx_GetSecurityData(tconn
);
453 if (rx_GetPacketCksum(apacket
) != 0)
454 cconn
->cksumSeen
= 1;
455 checkCksum
= cconn
->cksumSeen
;
456 tcp
= (struct rxkad_cprivate
*)aobj
->privateData
;
457 if (!(tcp
->type
& rxkad_client
))
458 return RXKADINCONSISTENCY
;
460 INC_RXKAD_STATS(checkPackets
[rxkad_StatIndex(rxkad_client
, level
)]);
461 cconn
->stats
.packetsReceived
++;
462 cconn
->stats
.bytesReceived
+= len
;
463 preSeq
= cconn
->preSeq
;
464 schedule
= (const fc_KeySchedule
*) tcp
->keysched
;
465 ivec
= (fc_InitializationVector
*) tcp
->ivec
;
469 code
= ComputeSum(apacket
, (fc_KeySchedule
*)schedule
, preSeq
);
470 if (code
!= rx_GetPacketCksum(apacket
))
471 return RXKADSEALEDINCON
;
476 return 0; /* shouldn't happen */
478 rx_Pullup(apacket
, 8); /* the following encrypts 8 bytes only */
479 fc_ecb_encrypt(rx_DataOf(apacket
), rx_DataOf(apacket
), *schedule
,
483 code
= rxkad_DecryptPacket(tconn
, schedule
, (const fc_InitializationVector
*)ivec
, len
, apacket
);
488 word
= ntohl(rx_GetInt32(apacket
, 0)); /* get first sealed word */
490 ((apacket
->header
.seq
^ apacket
->header
.callNumber
) & 0xffff))
491 return RXKADSEALEDINCON
;
492 nlen
= word
& 0xffff; /* get real user data length */
494 /* The sealed length should be no larger than the initial length, since the
495 * reverse (round-up) occurs in ...PreparePacket */
498 rx_SetDataSize(apacket
, nlen
);
502 /* either: encode packet */
505 rxkad_PreparePacket(struct rx_securityClass
*aobj
, struct rx_call
*acall
,
506 struct rx_packet
*apacket
)
508 struct rx_connection
*tconn
;
510 fc_KeySchedule
*schedule
;
511 fc_InitializationVector
*ivec
;
518 tconn
= rx_ConnectionOf(acall
);
519 len
= rx_GetDataSize(apacket
);
520 if (rx_IsServerConn(tconn
)) {
521 struct rxkad_sconn
*sconn
;
522 sconn
= rx_GetSecurityData(tconn
);
523 if (sconn
&& sconn
->authenticated
524 && (osi_Time() < sconn
->expirationTime
)) {
525 level
= sconn
->level
;
526 INC_RXKAD_STATS(preparePackets
[rxkad_StatIndex(rxkad_server
, level
)]);
527 sconn
->stats
.packetsSent
++;
528 sconn
->stats
.bytesSent
+= len
;
529 schedule
= (fc_KeySchedule
*) sconn
->keysched
;
530 ivec
= (fc_InitializationVector
*) sconn
->ivec
;
532 INC_RXKAD_STATS(expired
); /* this is a pretty unlikely path... */
535 preSeq
= sconn
->preSeq
;
536 } else { /* client connection */
537 struct rxkad_cconn
*cconn
;
538 struct rxkad_cprivate
*tcp
;
539 cconn
= rx_GetSecurityData(tconn
);
540 tcp
= (struct rxkad_cprivate
*)aobj
->privateData
;
541 if (!(tcp
->type
& rxkad_client
))
542 return RXKADINCONSISTENCY
;
544 INC_RXKAD_STATS(preparePackets
[rxkad_StatIndex(rxkad_client
, level
)]);
545 cconn
->stats
.packetsSent
++;
546 cconn
->stats
.bytesSent
+= len
;
547 preSeq
= cconn
->preSeq
;
548 schedule
= (fc_KeySchedule
*) tcp
->keysched
;
549 ivec
= (fc_InitializationVector
*) tcp
->ivec
;
552 /* compute upward compatible checksum */
553 rx_SetPacketCksum(apacket
, ComputeSum(apacket
, schedule
, preSeq
));
554 if (level
== rxkad_clear
)
557 len
= rx_GetDataSize(apacket
);
558 word
= (((apacket
->header
.seq
^ apacket
->header
.callNumber
)
559 & 0xffff) << 16) | (len
& 0xffff);
560 rx_PutInt32(apacket
, 0, htonl(word
));
564 return 0; /* shouldn't happen */
567 afs_max(ENCRYPTIONBLOCKSIZE
,
568 len
+ rx_GetSecurityHeaderSize(tconn
));
569 if (nlen
> (len
+ rx_GetSecurityHeaderSize(tconn
))) {
570 rxi_RoundUpPacket(apacket
,
571 nlen
- (len
+ rx_GetSecurityHeaderSize(tconn
)));
573 rx_Pullup(apacket
, 8); /* the following encrypts 8 bytes only */
574 fc_ecb_encrypt(rx_DataOf(apacket
), rx_DataOf(apacket
), *schedule
,
578 nlen
= round_up_to_ebs(len
+ rx_GetSecurityHeaderSize(tconn
));
579 if (nlen
> (len
+ rx_GetSecurityHeaderSize(tconn
))) {
580 rxi_RoundUpPacket(apacket
,
581 nlen
- (len
+ rx_GetSecurityHeaderSize(tconn
)));
583 code
= rxkad_EncryptPacket(tconn
, (const fc_KeySchedule
*)schedule
, (const fc_InitializationVector
*)ivec
, nlen
, apacket
);
588 rx_SetDataSize(apacket
, nlen
);
592 /* either: return connection stats */
595 rxkad_GetStats(struct rx_securityClass
*aobj
, struct rx_connection
*aconn
,
596 struct rx_securityObjectStats
*astats
)
600 astats
->type
= RX_SECTYPE_KAD
;
601 astats
->level
= ((struct rxkad_cprivate
*)aobj
->privateData
)->level
;
603 securityData
= rx_GetSecurityData(aconn
);
609 if (rx_IsServerConn(aconn
)) {
610 struct rxkad_sconn
*sconn
= securityData
;
612 astats
->level
= sconn
->level
;
613 if (sconn
->authenticated
)
615 if (sconn
->cksumSeen
)
617 astats
->expires
= sconn
->expirationTime
;
618 astats
->bytesReceived
= sconn
->stats
.bytesReceived
;
619 astats
->packetsReceived
= sconn
->stats
.packetsReceived
;
620 astats
->bytesSent
= sconn
->stats
.bytesSent
;
621 astats
->packetsSent
= sconn
->stats
.packetsSent
;
622 } else { /* client connection */
623 struct rxkad_cconn
*cconn
= securityData
;
625 if (cconn
->cksumSeen
)
627 astats
->bytesReceived
= cconn
->stats
.bytesReceived
;
628 astats
->packetsReceived
= cconn
->stats
.packetsReceived
;
629 astats
->bytesSent
= cconn
->stats
.bytesSent
;
630 astats
->packetsSent
= cconn
->stats
.packetsSent
;
636 rxkad_StringToLevel(char *name
)
638 if (strcmp(name
, "clear") == 0)
640 if (strcmp(name
, "auth") == 0)
642 if (strcmp(name
, "crypt") == 0)
648 rxkad_LevelToString(rxkad_level level
)
650 if (level
== rxkad_clear
)
652 if (level
== rxkad_auth
)
654 if (level
== rxkad_crypt
)