1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains source for the internal Zephyr routines.
4 * Created by: Robert French
6 * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of
8 * For copying and distribution information, see the file
16 #ifndef ZEPHYR_USES_KERBEROS
17 int gettimeofday(struct timeval
* p
, struct timezone
* tz
){
19 long long ns100
; /*time since 1 Jan 1601 in 100ns units */
23 GetSystemTimeAsFileTime( &(_now
.ft
) );
24 p
->tv_usec
=(long)((_now
.ns100
/ 10LL) % 1000000LL );
25 p
->tv_sec
= (long)((_now
.ns100
-(116444736000000000LL))/10000000LL);
31 #include <arpa/inet.h>
32 #include <sys/socket.h>
37 int __Zephyr_port
= -1;
38 struct in_addr __My_addr
;
39 int __Q_CompleteLength
;
41 struct _Z_InputQ
*__Q_Head
, *__Q_Tail
;
42 struct sockaddr_in __HM_addr
;
43 struct sockaddr_in __HM_addr_real
;
46 ZLocations_t
*__locate_list
;
49 ZSubscription_t
*__subscriptions_list
;
50 int __subscriptions_num
;
51 int __subscriptions_next
;
52 int Z_discarded_packets
= 0;
54 #ifdef ZEPHYR_USES_KERBEROS
55 C_Block __Zephyr_session
;
57 char __Zephyr_realm
[REALM_SZ
];
60 void (*__Z_debug_print
)(const char *fmt
, va_list args
, void *closure
);
61 void *__Z_debug_print_closure
;
64 static int Z_AddField(char **ptr
, const char *field
, char *end
);
65 static int find_or_insert_uid(ZUnique_Id_t
*uid
, ZNotice_Kind_t kind
);
67 /* Find or insert uid in the old uids buffer. The buffer is a sorted
68 * circular queue. We make the assumption that most packets arrive in
69 * order, so we can usually search for a uid or insert it into the buffer
70 * by looking back just a few entries from the end. Since this code is
71 * only executed by the client, the implementation isn't microoptimized. */
72 static int find_or_insert_uid(uid
, kind
)
76 static struct _filter
{
90 /* Initialize the uid buffer if it hasn't been done already. */
92 size
= Z_INITFILTERSIZE
;
93 buffer
= (struct _filter
*) malloc(size
* sizeof(*buffer
));
98 /* Age the uid buffer, discarding any uids older than the clock skew. */
100 while (num
&& (now
- buffer
[start
% size
].t
) > CLOCK_SKEW
)
104 /* Make room for a new uid, since we'll probably have to insert one. */
106 new_size
= size
* 2 + 2;
107 new = (struct _filter
*) malloc(new_size
* sizeof(*new));
110 for (i
= 0; i
< num
; i
++)
111 new[i
] = buffer
[(start
+ i
) % size
];
118 /* Search for this uid in the buffer, starting from the end. */
119 for (i
= start
+ num
- 1; i
>= start
; i
--) {
120 result
= memcmp(uid
, &buffer
[i
% size
].uid
, sizeof(*uid
));
121 if (result
== 0 && buffer
[i
% size
].kind
== kind
)
127 /* We didn't find it; insert the uid into the buffer after i. */
129 for (j
= start
+ num
; j
> i
; j
--)
130 buffer
[j
% size
] = buffer
[(j
- 1) % size
];
131 buffer
[i
% size
].uid
= *uid
;
132 buffer
[i
% size
].kind
= kind
;
133 buffer
[i
% size
].t
= now
;
140 /* Return 1 if there is a packet waiting, 0 otherwise */
142 static int Z_PacketWaiting(void)
147 tv
.tv_sec
= tv
.tv_usec
= 0;
149 FD_SET(ZGetFD(), &read
);
150 return (select(ZGetFD() + 1, &read
, NULL
, NULL
, &tv
));
154 /* Wait for a complete notice to become available */
156 Code_t
Z_WaitForComplete(void)
160 if (__Q_CompleteLength
)
161 return (Z_ReadEnqueue());
163 while (!__Q_CompleteLength
)
164 if ((retval
= Z_ReadWait()) != ZERR_NONE
)
171 /* Read any available packets and enqueue them */
173 Code_t
Z_ReadEnqueue()
178 return (ZERR_NOPORT
);
180 while (Z_PacketWaiting())
181 if ((retval
= Z_ReadWait()) != ZERR_NONE
)
189 * Search the queue for a notice with the proper multiuid - remove any
190 * notices that haven't been touched in a while
193 static struct _Z_InputQ
*Z_SearchQueue(ZUnique_Id_t
*uid
, ZNotice_Kind_t kind
)
195 register struct _Z_InputQ
*qptr
;
196 struct _Z_InputQ
*next
;
199 (void) gettimeofday(&tv
, (struct timezone
*)0);
204 if (ZCompareUID(uid
, &qptr
->uid
) && qptr
->kind
== kind
)
207 if (qptr
->timep
&& ((time_t)qptr
->timep
+Z_NOTICETIMELIMIT
< tv
.tv_sec
))
215 * Now we delve into really convoluted queue handling and
216 * fragmentation reassembly algorithms and other stuff you probably
217 * don't want to look at...
219 * This routine does NOT guarantee a complete packet will be ready when it
225 register struct _Z_InputQ
*qptr
;
228 struct sockaddr_in olddest
, from
;
229 int packet_len
, zvlen
, part
, partof
;
237 return (ZERR_NOPORT
);
240 FD_SET(ZGetFD(), &fds
);
244 if (select(ZGetFD() + 1, &fds
, NULL
, NULL
, &tv
) < 0)
246 if (!FD_ISSET(ZGetFD(), &fds
))
249 from_len
= sizeof(struct sockaddr_in
);
251 packet_len
= recvfrom(ZGetFD(), packet
, sizeof(packet
) - 1, 0,
252 (struct sockaddr
*)&from
, &from_len
);
260 packet
[packet_len
] = '\0';
262 /* Ignore obviously non-Zephyr packets. */
263 zvlen
= sizeof(ZVERSIONHDR
) - 1;
264 if (packet_len
< zvlen
|| memcmp(packet
, ZVERSIONHDR
, zvlen
) != 0) {
265 Z_discarded_packets
++;
269 /* Parse the notice */
270 if ((retval
= ZParseNotice(packet
, packet_len
, ¬ice
)) != ZERR_NONE
)
274 * If we're not a server and the notice is of an appropriate kind,
275 * send back a CLIENTACK to whoever sent it to say we got it.
277 if (!__Zephyr_server
) {
278 if (notice
.z_kind
!= HMACK
&& notice
.z_kind
!= SERVACK
&&
279 notice
.z_kind
!= SERVNAK
&& notice
.z_kind
!= CLIENTACK
) {
285 tmpnotice
.z_kind
= CLIENTACK
;
286 tmpnotice
.z_message_len
= 0;
289 if ((retval
= ZFormatSmallRawNotice(&tmpnotice
, pkt
, &len
))
292 if ((retval
= ZSendPacket(pkt
, len
, 0)) != ZERR_NONE
)
296 if (find_or_insert_uid(¬ice
.z_uid
, notice
.z_kind
))
299 /* Check authentication on the notice. */
300 notice
.z_checked_auth
= ZCheckAuthentication(¬ice
, &from
);
305 * Parse apart the z_multinotice field - if the field is blank for
306 * some reason, assume this packet stands by itself.
308 slash
= strchr(notice
.z_multinotice
, '/');
310 part
= atoi(notice
.z_multinotice
);
311 partof
= atoi(slash
+1);
312 if (part
> partof
|| partof
== 0) {
314 partof
= notice
.z_message_len
;
319 partof
= notice
.z_message_len
;
322 /* Too big a packet...just ignore it! */
323 if (partof
> Z_MAXNOTICESIZE
)
327 * If we aren't a server and we can find a notice in the queue
328 * with the same multiuid field, insert the current fragment as
331 switch (notice
.z_kind
) {
334 /* The SERVACK and SERVNAK replies shouldn't be reassembled
335 (they have no parts). Instead, we should hold on to the reply
336 ONLY if it's the first part of a fragmented message, i.e.
337 multi_uid == uid. This allows programs to wait for the uid
338 of the first packet, and get a response when that notice
339 arrives. Acknowledgements of the other fragments are discarded
340 (XXX we assume here that they all carry the same information
341 regarding failure/success)
343 if (!__Zephyr_server
&&
344 !ZCompareUID(¬ice
.z_multiuid
, ¬ice
.z_uid
))
345 /* they're not the same... throw away this packet. */
347 /* fall thru & process it */
349 /* for HMACK types, we assume no packet loss (local loopback
350 connections). The other types can be fragmented and MUST
351 run through this code. */
352 if (!__Zephyr_server
&& (qptr
= Z_SearchQueue(¬ice
.z_multiuid
,
355 * If this is the first fragment, and we haven't already
356 * gotten a first fragment, grab the header from it.
358 if (part
== 0 && !qptr
->header
) {
359 qptr
->header_len
= packet_len
-notice
.z_message_len
;
360 qptr
->header
= (char *) malloc((unsigned) qptr
->header_len
);
363 (void) memcpy(qptr
->header
, packet
, qptr
->header_len
);
365 return (Z_AddNoticeToEntry(qptr
, ¬ice
, part
));
370 * We'll have to create a new entry...make sure the queue isn't
371 * going to get too big.
373 if (__Q_Size
+(__Zephyr_server
? notice
.z_message_len
: partof
) > Z_MAXQUEUESIZE
)
377 * This is a notice we haven't heard of, so create a new queue
378 * entry for it and zero it out.
380 qptr
= (struct _Z_InputQ
*)malloc(sizeof(struct _Z_InputQ
));
383 (void) memset((char *)qptr
, 0, sizeof(struct _Z_InputQ
));
385 /* Insert the entry at the end of the queue */
387 qptr
->prev
= __Q_Tail
;
389 __Q_Tail
->next
= qptr
;
396 /* Copy the from field, multiuid, kind, and checked authentication. */
398 qptr
->uid
= notice
.z_multiuid
;
399 qptr
->kind
= notice
.z_kind
;
400 qptr
->auth
= notice
.z_checked_auth
;
403 * If this is the first part of the notice, we take the header
404 * from it. We only take it if this is the first fragment so that
405 * the Unique ID's will be predictable.
407 * If a Zephyr Server, we always take the header.
409 if (__Zephyr_server
|| part
== 0) {
410 qptr
->header_len
= packet_len
-notice
.z_message_len
;
411 qptr
->header
= (char *) malloc((unsigned) qptr
->header_len
);
414 (void) memcpy(qptr
->header
, packet
, qptr
->header_len
);
418 * If this is not a fragmented notice, then don't bother with a
420 * If we are a Zephyr server, all notices are treated as complete.
422 if (__Zephyr_server
|| (part
== 0 && notice
.z_message_len
== partof
)) {
423 __Q_CompleteLength
++;
424 qptr
->holelist
= (struct _Z_Hole
*) 0;
426 /* allocate a msg buf for this piece */
427 if (notice
.z_message_len
== 0)
429 else if (!(qptr
->msg
= (char *) malloc((unsigned) notice
.z_message_len
)))
432 (void) memcpy(qptr
->msg
, notice
.z_message
, notice
.z_message_len
);
433 qptr
->msg_len
= notice
.z_message_len
;
434 __Q_Size
+= notice
.z_message_len
;
435 qptr
->packet_len
= qptr
->header_len
+qptr
->msg_len
;
436 if (!(qptr
->packet
= (char *) malloc((unsigned) qptr
->packet_len
)))
438 (void) memcpy(qptr
->packet
, qptr
->header
, qptr
->header_len
);
440 (void) memcpy(qptr
->packet
+qptr
->header_len
, qptr
->msg
,
446 * We know how long the message is going to be (this is better
447 * than IP fragmentation...), so go ahead and allocate it all.
449 if (!(qptr
->msg
= (char *) malloc((unsigned) partof
)) && partof
)
451 qptr
->msg_len
= partof
;
455 * Well, it's a fragmented notice...allocate a hole list and
456 * initialize it to the full packet size. Then insert the
459 if (!(qptr
->holelist
= (struct _Z_Hole
*)
460 malloc(sizeof(struct _Z_Hole
))))
462 qptr
->holelist
->next
= (struct _Z_Hole
*) 0;
463 qptr
->holelist
->first
= 0;
464 qptr
->holelist
->last
= partof
-1;
465 return (Z_AddNoticeToEntry(qptr
, ¬ice
, part
));
469 /* Fragment management routines - compliments, more or less, of RFC815 */
471 Code_t
Z_AddNoticeToEntry(qptr
, notice
, part
)
472 struct _Z_InputQ
*qptr
;
476 int last
, oldfirst
, oldlast
;
477 struct _Z_Hole
*hole
, *lasthole
;
480 /* Incorporate this notice's checked authentication. */
481 if (notice
->z_checked_auth
== ZAUTH_FAILED
)
482 qptr
->auth
= ZAUTH_FAILED
;
483 else if (notice
->z_checked_auth
== ZAUTH_NO
&& qptr
->auth
!= ZAUTH_FAILED
)
484 qptr
->auth
= ZAUTH_NO
;
486 (void) gettimeofday(&tv
, (struct timezone
*)0);
487 qptr
->timep
= tv
.tv_sec
;
489 last
= part
+notice
->z_message_len
-1;
491 hole
= qptr
->holelist
;
492 lasthole
= (struct _Z_Hole
*) 0;
494 /* copy in the message body */
495 (void) memcpy(qptr
->msg
+part
, notice
->z_message
, notice
->z_message_len
);
497 /* Search for a hole that overlaps with the current fragment */
499 if (part
<= hole
->last
&& last
>= hole
->first
)
505 /* If we found one, delete it and reconstruct a new hole */
507 oldfirst
= hole
->first
;
508 oldlast
= hole
->last
;
510 lasthole
->next
= hole
->next
;
512 qptr
->holelist
= hole
->next
;
515 * Now create a new hole that is the original hole without the
518 if (part
> oldfirst
) {
519 /* Search for the end of the hole list */
520 hole
= qptr
->holelist
;
521 lasthole
= (struct _Z_Hole
*) 0;
527 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
530 lasthole
->next
= (struct _Z_Hole
*)inputq
;
531 hole
= lasthole
->next
;
534 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
537 qptr
->holelist
= (struct _Z_Hole
*)inputq
;
538 hole
= qptr
->holelist
;
541 hole
->first
= oldfirst
;
544 if (last
< oldlast
) {
545 /* Search for the end of the hole list */
546 hole
= qptr
->holelist
;
547 lasthole
= (struct _Z_Hole
*) 0;
553 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
556 lasthole
->next
= (struct _Z_Hole
*)inputq
;
557 hole
= lasthole
->next
;
560 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
563 qptr
->holelist
= (struct _Z_Hole
*)inputq
;
564 hole
= qptr
->holelist
;
566 hole
->next
= (struct _Z_Hole
*) 0;
567 hole
->first
= last
+1;
568 hole
->last
= oldlast
;
572 if (!qptr
->holelist
) {
574 __Q_CompleteLength
++;
576 qptr
->timep
= 0; /* don't time out anymore */
577 qptr
->packet_len
= qptr
->header_len
+qptr
->msg_len
;
578 if (!(qptr
->packet
= (char *) malloc((unsigned) qptr
->packet_len
)))
580 (void) memcpy(qptr
->packet
, qptr
->header
, qptr
->header_len
);
581 (void) memcpy(qptr
->packet
+qptr
->header_len
, qptr
->msg
,
588 Code_t
Z_FormatHeader(notice
, buffer
, buffer_len
, len
, cert_routine
)
593 Z_AuthProc cert_routine
;
596 static char version
[BUFSIZ
]; /* default init should be all \0 */
597 struct sockaddr_in name
;
598 socklen_t namelen
= sizeof(name
);
600 if (!notice
->z_sender
)
601 notice
->z_sender
= ZGetSender();
603 if (notice
->z_port
== 0) {
605 retval
= ZOpenPort((unsigned short *)0);
606 if (retval
!= ZERR_NONE
)
609 retval
= getsockname(ZGetFD(), (struct sockaddr
*) &name
, &namelen
);
612 notice
->z_port
= name
.sin_port
;
615 notice
->z_multinotice
= "";
617 (void) gettimeofday(¬ice
->z_uid
.tv
, (struct timezone
*)0);
618 notice
->z_uid
.tv
.tv_sec
= htonl((unsigned long) notice
->z_uid
.tv
.tv_sec
);
619 notice
->z_uid
.tv
.tv_usec
= htonl((unsigned long) notice
->z_uid
.tv
.tv_usec
);
621 (void) memcpy(¬ice
->z_uid
.zuid_addr
, &__My_addr
, sizeof(__My_addr
));
623 notice
->z_multiuid
= notice
->z_uid
;
626 (void) sprintf(version
, "%s%d.%d", ZVERSIONHDR
, ZVERSIONMAJOR
,
628 notice
->z_version
= version
;
630 return Z_FormatAuthHeader(notice
, buffer
, buffer_len
, len
, cert_routine
);
633 Code_t
Z_FormatAuthHeader(notice
, buffer
, buffer_len
, len
, cert_routine
)
638 Z_AuthProc cert_routine
;
642 notice
->z_authent_len
= 0;
643 notice
->z_ascii_authent
= "";
644 notice
->z_checksum
= 0;
645 return (Z_FormatRawHeader(notice
, buffer
, buffer_len
,
649 return ((*cert_routine
)(notice
, buffer
, buffer_len
, len
));
652 Code_t
Z_FormatRawHeader(notice
, buffer
, buffer_len
, len
, cstart
, cend
)
657 char **cstart
, **cend
;
659 char newrecip
[BUFSIZ
];
663 if (!notice
->z_class
)
664 notice
->z_class
= "";
666 if (!notice
->z_class_inst
)
667 notice
->z_class_inst
= "";
669 if (!notice
->z_opcode
)
670 notice
->z_opcode
= "";
672 if (!notice
->z_recipient
)
673 notice
->z_recipient
= "";
675 if (!notice
->z_default_format
)
676 notice
->z_default_format
= "";
679 end
= buffer
+buffer_len
;
681 if (buffer_len
< strlen(notice
->z_version
)+1)
682 return (ZERR_HEADERLEN
);
684 g_strlcpy(ptr
, notice
->z_version
, buffer_len
);
685 ptr
+= strlen(ptr
)+1;
687 if (ZMakeAscii32(ptr
, end
-ptr
, Z_NUMFIELDS
+ notice
->z_num_other_fields
)
689 return (ZERR_HEADERLEN
);
690 ptr
+= strlen(ptr
)+1;
692 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_kind
) == ZERR_FIELDLEN
)
693 return (ZERR_HEADERLEN
);
694 ptr
+= strlen(ptr
)+1;
696 if (ZMakeAscii(ptr
, end
-ptr
, (unsigned char *)¬ice
->z_uid
,
697 sizeof(ZUnique_Id_t
)) == ZERR_FIELDLEN
)
698 return (ZERR_HEADERLEN
);
699 ptr
+= strlen(ptr
)+1;
701 if (ZMakeAscii16(ptr
, end
-ptr
, ntohs(notice
->z_port
)) == ZERR_FIELDLEN
)
702 return (ZERR_HEADERLEN
);
703 ptr
+= strlen(ptr
)+1;
705 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_auth
) == ZERR_FIELDLEN
)
706 return (ZERR_HEADERLEN
);
707 ptr
+= strlen(ptr
)+1;
709 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_authent_len
) == ZERR_FIELDLEN
)
710 return (ZERR_HEADERLEN
);
711 ptr
+= strlen(ptr
)+1;
713 if (Z_AddField(&ptr
, notice
->z_ascii_authent
, end
))
714 return (ZERR_HEADERLEN
);
715 if (Z_AddField(&ptr
, notice
->z_class
, end
))
716 return (ZERR_HEADERLEN
);
717 if (Z_AddField(&ptr
, notice
->z_class_inst
, end
))
718 return (ZERR_HEADERLEN
);
719 if (Z_AddField(&ptr
, notice
->z_opcode
, end
))
720 return (ZERR_HEADERLEN
);
721 if (Z_AddField(&ptr
, notice
->z_sender
, end
))
722 return (ZERR_HEADERLEN
);
723 if (strchr(notice
->z_recipient
, '@') || !*notice
->z_recipient
) {
724 if (Z_AddField(&ptr
, notice
->z_recipient
, end
))
725 return (ZERR_HEADERLEN
);
728 if (strlen(notice
->z_recipient
) + strlen(__Zephyr_realm
) + 2 >
730 return (ZERR_HEADERLEN
);
731 (void) sprintf(newrecip
, "%s@%s", notice
->z_recipient
, __Zephyr_realm
);
732 if (Z_AddField(&ptr
, newrecip
, end
))
733 return (ZERR_HEADERLEN
);
735 if (Z_AddField(&ptr
, notice
->z_default_format
, end
))
736 return (ZERR_HEADERLEN
);
738 /* copy back the end pointer location for crypto checksum */
741 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_checksum
) == ZERR_FIELDLEN
)
742 return (ZERR_HEADERLEN
);
743 ptr
+= strlen(ptr
)+1;
747 if (Z_AddField(&ptr
, notice
->z_multinotice
, end
))
748 return (ZERR_HEADERLEN
);
750 if (ZMakeAscii(ptr
, end
-ptr
, (unsigned char *)¬ice
->z_multiuid
,
751 sizeof(ZUnique_Id_t
)) == ZERR_FIELDLEN
)
752 return (ZERR_HEADERLEN
);
753 ptr
+= strlen(ptr
)+1;
755 for (i
=0;i
<notice
->z_num_other_fields
;i
++)
756 if (Z_AddField(&ptr
, notice
->z_other_fields
[i
], end
))
757 return (ZERR_HEADERLEN
);
765 Z_AddField(char **ptr
, const char *field
, char *end
)
769 len
= field
? strlen (field
) + 1 : 1;
782 struct _Z_InputQ
*Z_GetFirstComplete()
784 struct _Z_InputQ
*qptr
;
794 return ((struct _Z_InputQ
*)0);
797 struct _Z_InputQ
*Z_GetNextComplete(qptr
)
798 struct _Z_InputQ
*qptr
;
807 return ((struct _Z_InputQ
*)0);
810 void Z_RemQueue(qptr
)
811 struct _Z_InputQ
*qptr
;
813 struct _Z_Hole
*hole
, *nexthole
;
816 __Q_CompleteLength
--;
818 __Q_Size
-= qptr
->msg_len
;
824 hole
= qptr
->holelist
;
826 nexthole
= hole
->next
;
831 if (qptr
== __Q_Head
&& __Q_Head
== __Q_Tail
) {
833 __Q_Head
= (struct _Z_InputQ
*)0;
834 __Q_Tail
= (struct _Z_InputQ
*)0;
838 if (qptr
== __Q_Head
) {
839 __Q_Head
= qptr
->next
;
840 __Q_Head
->prev
= (struct _Z_InputQ
*)0;
844 if (qptr
== __Q_Tail
) {
845 __Q_Tail
= qptr
->prev
;
846 __Q_Tail
->next
= (struct _Z_InputQ
*)0;
850 qptr
->prev
->next
= qptr
->next
;
851 qptr
->next
->prev
= qptr
->prev
;
856 Code_t
Z_SendFragmentedNotice(notice
, len
, cert_func
, send_func
)
859 Z_AuthProc cert_func
;
860 Z_SendProc send_func
;
862 ZNotice_t partnotice
;
865 int offset
, hdrsize
, fragsize
, ret_len
, message_len
, waitforack
;
868 hdrsize
= len
-notice
->z_message_len
;
869 fragsize
= Z_MAXPKTLEN
-hdrsize
-Z_FRAGFUDGE
;
873 waitforack
= ((notice
->z_kind
== UNACKED
|| notice
->z_kind
== ACKED
)
874 && !__Zephyr_server
);
876 partnotice
= *notice
;
878 while (offset
< notice
->z_message_len
|| !notice
->z_message_len
) {
879 (void) sprintf(multi
, "%d/%d", offset
, notice
->z_message_len
);
880 partnotice
.z_multinotice
= multi
;
882 (void) gettimeofday(&partnotice
.z_uid
.tv
,
883 (struct timezone
*)0);
884 partnotice
.z_uid
.tv
.tv_sec
=
885 htonl((unsigned long) partnotice
.z_uid
.tv
.tv_sec
);
886 partnotice
.z_uid
.tv
.tv_usec
=
887 htonl((unsigned long) partnotice
.z_uid
.tv
.tv_usec
);
888 (void) memcpy((char *)&partnotice
.z_uid
.zuid_addr
, &__My_addr
,
891 message_len
= MIN(notice
->z_message_len
- offset
, fragsize
);
892 partnotice
.z_message
= (char*)notice
->z_message
+offset
;
893 partnotice
.z_message_len
= message_len
;
894 if ((retval
= Z_FormatAuthHeader(&partnotice
, buffer
, Z_MAXHEADERLEN
,
895 &ret_len
, cert_func
)) != ZERR_NONE
) {
898 memcpy(buffer
+ ret_len
, partnotice
.z_message
, message_len
);
899 if ((retval
= (*send_func
)(&partnotice
, buffer
, ret_len
+message_len
,
900 waitforack
)) != ZERR_NONE
) {
904 if (!notice
->z_message_len
)
912 Code_t
Z_XmitFragment(notice
, buf
, len
, wait
)
918 return(ZSendPacket(buf
, len
, wait
));
922 /* For debugging printing */
923 const char *const ZNoticeKinds
[] = {
924 "UNSAFE", "UNACKED", "ACKED", "HMACK", "HMCTL", "SERVACK", "SERVNAK",
932 void Z_debug (const char *format
, ...)
935 if (!__Z_debug_print
)
937 va_start (pvar
, format
);
938 (*__Z_debug_print
) (format
, pvar
, __Z_debug_print_closure
);
942 void Z_debug_stderr (format
, args
, closure
)
947 vfprintf (stderr
, format
, args
);
952 int ZGetFD () { return __Zephyr_fd
; }
955 int ZQLength () { return __Q_CompleteLength
; }
958 struct sockaddr_in
ZGetDestAddr () { return __HM_addr
; }
961 Zconst
char * ZGetRealm () { return __Zephyr_realm
; }
964 void ZSetDebug(proc
, arg
)
965 void (*proc
)(const char *, va_list, void *);
968 __Z_debug_print
= proc
;
969 __Z_debug_print_closure
= arg
;