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
) __P((const char *fmt
, va_list args
, void *closure
));
61 void *__Z_debug_print_closure
;
64 #define min(a,b) ((a)<(b)?(a):(b))
66 static int Z_AddField
__P((char **ptr
, const char *field
, char *end
));
67 static int find_or_insert_uid
__P((ZUnique_Id_t
*uid
, ZNotice_Kind_t kind
));
69 /* Find or insert uid in the old uids buffer. The buffer is a sorted
70 * circular queue. We make the assumption that most packets arrive in
71 * order, so we can usually search for a uid or insert it into the buffer
72 * by looking back just a few entries from the end. Since this code is
73 * only executed by the client, the implementation isn't microoptimized. */
74 static int find_or_insert_uid(uid
, kind
)
78 static struct _filter
{
92 /* Initialize the uid buffer if it hasn't been done already. */
94 size
= Z_INITFILTERSIZE
;
95 buffer
= (struct _filter
*) malloc(size
* sizeof(*buffer
));
100 /* Age the uid buffer, discarding any uids older than the clock skew. */
102 while (num
&& (now
- buffer
[start
% size
].t
) > CLOCK_SKEW
)
106 /* Make room for a new uid, since we'll probably have to insert one. */
108 new_size
= size
* 2 + 2;
109 new = (struct _filter
*) malloc(new_size
* sizeof(*new));
112 for (i
= 0; i
< num
; i
++)
113 new[i
] = buffer
[(start
+ i
) % size
];
120 /* Search for this uid in the buffer, starting from the end. */
121 for (i
= start
+ num
- 1; i
>= start
; i
--) {
122 result
= memcmp(uid
, &buffer
[i
% size
].uid
, sizeof(*uid
));
123 if (result
== 0 && buffer
[i
% size
].kind
== kind
)
129 /* We didn't find it; insert the uid into the buffer after i. */
131 for (j
= start
+ num
; j
> i
; j
--)
132 buffer
[j
% size
] = buffer
[(j
- 1) % size
];
133 buffer
[i
% size
].uid
= *uid
;
134 buffer
[i
% size
].kind
= kind
;
135 buffer
[i
% size
].t
= now
;
142 /* Return 1 if there is a packet waiting, 0 otherwise */
144 static int Z_PacketWaiting(void)
149 tv
.tv_sec
= tv
.tv_usec
= 0;
151 FD_SET(ZGetFD(), &read
);
152 return (select(ZGetFD() + 1, &read
, NULL
, NULL
, &tv
));
156 /* Wait for a complete notice to become available */
158 Code_t
Z_WaitForComplete(void)
162 if (__Q_CompleteLength
)
163 return (Z_ReadEnqueue());
165 while (!__Q_CompleteLength
)
166 if ((retval
= Z_ReadWait()) != ZERR_NONE
)
173 /* Read any available packets and enqueue them */
175 Code_t
Z_ReadEnqueue()
180 return (ZERR_NOPORT
);
182 while (Z_PacketWaiting())
183 if ((retval
= Z_ReadWait()) != ZERR_NONE
)
191 * Search the queue for a notice with the proper multiuid - remove any
192 * notices that haven't been touched in a while
195 static struct _Z_InputQ
*Z_SearchQueue(ZUnique_Id_t
*uid
, ZNotice_Kind_t kind
)
197 register struct _Z_InputQ
*qptr
;
198 struct _Z_InputQ
*next
;
201 (void) gettimeofday(&tv
, (struct timezone
*)0);
206 if (ZCompareUID(uid
, &qptr
->uid
) && qptr
->kind
== kind
)
209 if (qptr
->timep
&& ((time_t)qptr
->timep
+Z_NOTICETIMELIMIT
< tv
.tv_sec
))
217 * Now we delve into really convoluted queue handling and
218 * fragmentation reassembly algorithms and other stuff you probably
219 * don't want to look at...
221 * This routine does NOT guarantee a complete packet will be ready when it
227 register struct _Z_InputQ
*qptr
;
230 struct sockaddr_in olddest
, from
;
231 int packet_len
, zvlen
, part
, partof
;
239 return (ZERR_NOPORT
);
242 FD_SET(ZGetFD(), &fds
);
246 if (select(ZGetFD() + 1, &fds
, NULL
, NULL
, &tv
) < 0)
248 if (!FD_ISSET(ZGetFD(), &fds
))
251 from_len
= sizeof(struct sockaddr_in
);
253 packet_len
= recvfrom(ZGetFD(), packet
, sizeof(packet
) - 1, 0,
254 (struct sockaddr
*)&from
, &from_len
);
262 packet
[packet_len
] = '\0';
264 /* Ignore obviously non-Zephyr packets. */
265 zvlen
= sizeof(ZVERSIONHDR
) - 1;
266 if (packet_len
< zvlen
|| memcmp(packet
, ZVERSIONHDR
, zvlen
) != 0) {
267 Z_discarded_packets
++;
271 /* Parse the notice */
272 if ((retval
= ZParseNotice(packet
, packet_len
, ¬ice
)) != ZERR_NONE
)
276 * If we're not a server and the notice is of an appropriate kind,
277 * send back a CLIENTACK to whoever sent it to say we got it.
279 if (!__Zephyr_server
) {
280 if (notice
.z_kind
!= HMACK
&& notice
.z_kind
!= SERVACK
&&
281 notice
.z_kind
!= SERVNAK
&& notice
.z_kind
!= CLIENTACK
) {
287 tmpnotice
.z_kind
= CLIENTACK
;
288 tmpnotice
.z_message_len
= 0;
291 if ((retval
= ZFormatSmallRawNotice(&tmpnotice
, pkt
, &len
))
294 if ((retval
= ZSendPacket(pkt
, len
, 0)) != ZERR_NONE
)
298 if (find_or_insert_uid(¬ice
.z_uid
, notice
.z_kind
))
301 /* Check authentication on the notice. */
302 notice
.z_checked_auth
= ZCheckAuthentication(¬ice
, &from
);
307 * Parse apart the z_multinotice field - if the field is blank for
308 * some reason, assume this packet stands by itself.
310 slash
= strchr(notice
.z_multinotice
, '/');
312 part
= atoi(notice
.z_multinotice
);
313 partof
= atoi(slash
+1);
314 if (part
> partof
|| partof
== 0) {
316 partof
= notice
.z_message_len
;
321 partof
= notice
.z_message_len
;
324 /* Too big a packet...just ignore it! */
325 if (partof
> Z_MAXNOTICESIZE
)
329 * If we aren't a server and we can find a notice in the queue
330 * with the same multiuid field, insert the current fragment as
333 switch (notice
.z_kind
) {
336 /* The SERVACK and SERVNAK replies shouldn't be reassembled
337 (they have no parts). Instead, we should hold on to the reply
338 ONLY if it's the first part of a fragmented message, i.e.
339 multi_uid == uid. This allows programs to wait for the uid
340 of the first packet, and get a response when that notice
341 arrives. Acknowledgements of the other fragments are discarded
342 (XXX we assume here that they all carry the same information
343 regarding failure/success)
345 if (!__Zephyr_server
&&
346 !ZCompareUID(¬ice
.z_multiuid
, ¬ice
.z_uid
))
347 /* they're not the same... throw away this packet. */
349 /* fall thru & process it */
351 /* for HMACK types, we assume no packet loss (local loopback
352 connections). The other types can be fragmented and MUST
353 run through this code. */
354 if (!__Zephyr_server
&& (qptr
= Z_SearchQueue(¬ice
.z_multiuid
,
357 * If this is the first fragment, and we haven't already
358 * gotten a first fragment, grab the header from it.
360 if (part
== 0 && !qptr
->header
) {
361 qptr
->header_len
= packet_len
-notice
.z_message_len
;
362 qptr
->header
= (char *) malloc((unsigned) qptr
->header_len
);
365 (void) memcpy(qptr
->header
, packet
, qptr
->header_len
);
367 return (Z_AddNoticeToEntry(qptr
, ¬ice
, part
));
372 * We'll have to create a new entry...make sure the queue isn't
373 * going to get too big.
375 if (__Q_Size
+(__Zephyr_server
? notice
.z_message_len
: partof
) > Z_MAXQUEUESIZE
)
379 * This is a notice we haven't heard of, so create a new queue
380 * entry for it and zero it out.
382 qptr
= (struct _Z_InputQ
*)malloc(sizeof(struct _Z_InputQ
));
385 (void) memset((char *)qptr
, 0, sizeof(struct _Z_InputQ
));
387 /* Insert the entry at the end of the queue */
389 qptr
->prev
= __Q_Tail
;
391 __Q_Tail
->next
= qptr
;
398 /* Copy the from field, multiuid, kind, and checked authentication. */
400 qptr
->uid
= notice
.z_multiuid
;
401 qptr
->kind
= notice
.z_kind
;
402 qptr
->auth
= notice
.z_checked_auth
;
405 * If this is the first part of the notice, we take the header
406 * from it. We only take it if this is the first fragment so that
407 * the Unique ID's will be predictable.
409 * If a Zephyr Server, we always take the header.
411 if (__Zephyr_server
|| part
== 0) {
412 qptr
->header_len
= packet_len
-notice
.z_message_len
;
413 qptr
->header
= (char *) malloc((unsigned) qptr
->header_len
);
416 (void) memcpy(qptr
->header
, packet
, qptr
->header_len
);
420 * If this is not a fragmented notice, then don't bother with a
422 * If we are a Zephyr server, all notices are treated as complete.
424 if (__Zephyr_server
|| (part
== 0 && notice
.z_message_len
== partof
)) {
425 __Q_CompleteLength
++;
426 qptr
->holelist
= (struct _Z_Hole
*) 0;
428 /* allocate a msg buf for this piece */
429 if (notice
.z_message_len
== 0)
431 else if (!(qptr
->msg
= (char *) malloc((unsigned) notice
.z_message_len
)))
434 (void) memcpy(qptr
->msg
, notice
.z_message
, notice
.z_message_len
);
435 qptr
->msg_len
= notice
.z_message_len
;
436 __Q_Size
+= notice
.z_message_len
;
437 qptr
->packet_len
= qptr
->header_len
+qptr
->msg_len
;
438 if (!(qptr
->packet
= (char *) malloc((unsigned) qptr
->packet_len
)))
440 (void) memcpy(qptr
->packet
, qptr
->header
, qptr
->header_len
);
442 (void) memcpy(qptr
->packet
+qptr
->header_len
, qptr
->msg
,
448 * We know how long the message is going to be (this is better
449 * than IP fragmentation...), so go ahead and allocate it all.
451 if (!(qptr
->msg
= (char *) malloc((unsigned) partof
)) && partof
)
453 qptr
->msg_len
= partof
;
457 * Well, it's a fragmented notice...allocate a hole list and
458 * initialize it to the full packet size. Then insert the
461 if (!(qptr
->holelist
= (struct _Z_Hole
*)
462 malloc(sizeof(struct _Z_Hole
))))
464 qptr
->holelist
->next
= (struct _Z_Hole
*) 0;
465 qptr
->holelist
->first
= 0;
466 qptr
->holelist
->last
= partof
-1;
467 return (Z_AddNoticeToEntry(qptr
, ¬ice
, part
));
471 /* Fragment management routines - compliments, more or less, of RFC815 */
473 Code_t
Z_AddNoticeToEntry(qptr
, notice
, part
)
474 struct _Z_InputQ
*qptr
;
478 int last
, oldfirst
, oldlast
;
479 struct _Z_Hole
*hole
, *lasthole
;
482 /* Incorporate this notice's checked authentication. */
483 if (notice
->z_checked_auth
== ZAUTH_FAILED
)
484 qptr
->auth
= ZAUTH_FAILED
;
485 else if (notice
->z_checked_auth
== ZAUTH_NO
&& qptr
->auth
!= ZAUTH_FAILED
)
486 qptr
->auth
= ZAUTH_NO
;
488 (void) gettimeofday(&tv
, (struct timezone
*)0);
489 qptr
->timep
= tv
.tv_sec
;
491 last
= part
+notice
->z_message_len
-1;
493 hole
= qptr
->holelist
;
494 lasthole
= (struct _Z_Hole
*) 0;
496 /* copy in the message body */
497 (void) memcpy(qptr
->msg
+part
, notice
->z_message
, notice
->z_message_len
);
499 /* Search for a hole that overlaps with the current fragment */
501 if (part
<= hole
->last
&& last
>= hole
->first
)
507 /* If we found one, delete it and reconstruct a new hole */
509 oldfirst
= hole
->first
;
510 oldlast
= hole
->last
;
512 lasthole
->next
= hole
->next
;
514 qptr
->holelist
= hole
->next
;
517 * Now create a new hole that is the original hole without the
520 if (part
> oldfirst
) {
521 /* Search for the end of the hole list */
522 hole
= qptr
->holelist
;
523 lasthole
= (struct _Z_Hole
*) 0;
529 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
532 lasthole
->next
= (struct _Z_Hole
*)inputq
;
533 hole
= lasthole
->next
;
536 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
539 qptr
->holelist
= (struct _Z_Hole
*)inputq
;
540 hole
= qptr
->holelist
;
543 hole
->first
= oldfirst
;
546 if (last
< oldlast
) {
547 /* Search for the end of the hole list */
548 hole
= qptr
->holelist
;
549 lasthole
= (struct _Z_Hole
*) 0;
555 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
558 lasthole
->next
= (struct _Z_Hole
*)inputq
;
559 hole
= lasthole
->next
;
562 struct _Z_InputQ
*inputq
= malloc(sizeof(struct _Z_InputQ
));
565 qptr
->holelist
= (struct _Z_Hole
*)inputq
;
566 hole
= qptr
->holelist
;
568 hole
->next
= (struct _Z_Hole
*) 0;
569 hole
->first
= last
+1;
570 hole
->last
= oldlast
;
574 if (!qptr
->holelist
) {
576 __Q_CompleteLength
++;
578 qptr
->timep
= 0; /* don't time out anymore */
579 qptr
->packet_len
= qptr
->header_len
+qptr
->msg_len
;
580 if (!(qptr
->packet
= (char *) malloc((unsigned) qptr
->packet_len
)))
582 (void) memcpy(qptr
->packet
, qptr
->header
, qptr
->header_len
);
583 (void) memcpy(qptr
->packet
+qptr
->header_len
, qptr
->msg
,
590 Code_t
Z_FormatHeader(notice
, buffer
, buffer_len
, len
, cert_routine
)
595 Z_AuthProc cert_routine
;
598 static char version
[BUFSIZ
]; /* default init should be all \0 */
599 struct sockaddr_in name
;
600 socklen_t namelen
= sizeof(name
);
602 if (!notice
->z_sender
)
603 notice
->z_sender
= ZGetSender();
605 if (notice
->z_port
== 0) {
607 retval
= ZOpenPort((unsigned short *)0);
608 if (retval
!= ZERR_NONE
)
611 retval
= getsockname(ZGetFD(), (struct sockaddr
*) &name
, &namelen
);
614 notice
->z_port
= name
.sin_port
;
617 notice
->z_multinotice
= "";
619 (void) gettimeofday(¬ice
->z_uid
.tv
, (struct timezone
*)0);
620 notice
->z_uid
.tv
.tv_sec
= htonl((unsigned long) notice
->z_uid
.tv
.tv_sec
);
621 notice
->z_uid
.tv
.tv_usec
= htonl((unsigned long) notice
->z_uid
.tv
.tv_usec
);
623 (void) memcpy(¬ice
->z_uid
.zuid_addr
, &__My_addr
, sizeof(__My_addr
));
625 notice
->z_multiuid
= notice
->z_uid
;
628 (void) sprintf(version
, "%s%d.%d", ZVERSIONHDR
, ZVERSIONMAJOR
,
630 notice
->z_version
= version
;
632 return Z_FormatAuthHeader(notice
, buffer
, buffer_len
, len
, cert_routine
);
635 Code_t
Z_FormatAuthHeader(notice
, buffer
, buffer_len
, len
, cert_routine
)
640 Z_AuthProc cert_routine
;
644 notice
->z_authent_len
= 0;
645 notice
->z_ascii_authent
= "";
646 notice
->z_checksum
= 0;
647 return (Z_FormatRawHeader(notice
, buffer
, buffer_len
,
651 return ((*cert_routine
)(notice
, buffer
, buffer_len
, len
));
654 Code_t
Z_FormatRawHeader(notice
, buffer
, buffer_len
, len
, cstart
, cend
)
659 char **cstart
, **cend
;
661 char newrecip
[BUFSIZ
];
665 if (!notice
->z_class
)
666 notice
->z_class
= "";
668 if (!notice
->z_class_inst
)
669 notice
->z_class_inst
= "";
671 if (!notice
->z_opcode
)
672 notice
->z_opcode
= "";
674 if (!notice
->z_recipient
)
675 notice
->z_recipient
= "";
677 if (!notice
->z_default_format
)
678 notice
->z_default_format
= "";
681 end
= buffer
+buffer_len
;
683 if (buffer_len
< strlen(notice
->z_version
)+1)
684 return (ZERR_HEADERLEN
);
686 g_strlcpy(ptr
, notice
->z_version
, buffer_len
);
687 ptr
+= strlen(ptr
)+1;
689 if (ZMakeAscii32(ptr
, end
-ptr
, Z_NUMFIELDS
+ notice
->z_num_other_fields
)
691 return (ZERR_HEADERLEN
);
692 ptr
+= strlen(ptr
)+1;
694 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_kind
) == ZERR_FIELDLEN
)
695 return (ZERR_HEADERLEN
);
696 ptr
+= strlen(ptr
)+1;
698 if (ZMakeAscii(ptr
, end
-ptr
, (unsigned char *)¬ice
->z_uid
,
699 sizeof(ZUnique_Id_t
)) == ZERR_FIELDLEN
)
700 return (ZERR_HEADERLEN
);
701 ptr
+= strlen(ptr
)+1;
703 if (ZMakeAscii16(ptr
, end
-ptr
, ntohs(notice
->z_port
)) == ZERR_FIELDLEN
)
704 return (ZERR_HEADERLEN
);
705 ptr
+= strlen(ptr
)+1;
707 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_auth
) == ZERR_FIELDLEN
)
708 return (ZERR_HEADERLEN
);
709 ptr
+= strlen(ptr
)+1;
711 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_authent_len
) == ZERR_FIELDLEN
)
712 return (ZERR_HEADERLEN
);
713 ptr
+= strlen(ptr
)+1;
715 if (Z_AddField(&ptr
, notice
->z_ascii_authent
, end
))
716 return (ZERR_HEADERLEN
);
717 if (Z_AddField(&ptr
, notice
->z_class
, end
))
718 return (ZERR_HEADERLEN
);
719 if (Z_AddField(&ptr
, notice
->z_class_inst
, end
))
720 return (ZERR_HEADERLEN
);
721 if (Z_AddField(&ptr
, notice
->z_opcode
, end
))
722 return (ZERR_HEADERLEN
);
723 if (Z_AddField(&ptr
, notice
->z_sender
, end
))
724 return (ZERR_HEADERLEN
);
725 if (strchr(notice
->z_recipient
, '@') || !*notice
->z_recipient
) {
726 if (Z_AddField(&ptr
, notice
->z_recipient
, end
))
727 return (ZERR_HEADERLEN
);
730 if (strlen(notice
->z_recipient
) + strlen(__Zephyr_realm
) + 2 >
732 return (ZERR_HEADERLEN
);
733 (void) sprintf(newrecip
, "%s@%s", notice
->z_recipient
, __Zephyr_realm
);
734 if (Z_AddField(&ptr
, newrecip
, end
))
735 return (ZERR_HEADERLEN
);
737 if (Z_AddField(&ptr
, notice
->z_default_format
, end
))
738 return (ZERR_HEADERLEN
);
740 /* copy back the end pointer location for crypto checksum */
743 if (ZMakeAscii32(ptr
, end
-ptr
, notice
->z_checksum
) == ZERR_FIELDLEN
)
744 return (ZERR_HEADERLEN
);
745 ptr
+= strlen(ptr
)+1;
749 if (Z_AddField(&ptr
, notice
->z_multinotice
, end
))
750 return (ZERR_HEADERLEN
);
752 if (ZMakeAscii(ptr
, end
-ptr
, (unsigned char *)¬ice
->z_multiuid
,
753 sizeof(ZUnique_Id_t
)) == ZERR_FIELDLEN
)
754 return (ZERR_HEADERLEN
);
755 ptr
+= strlen(ptr
)+1;
757 for (i
=0;i
<notice
->z_num_other_fields
;i
++)
758 if (Z_AddField(&ptr
, notice
->z_other_fields
[i
], end
))
759 return (ZERR_HEADERLEN
);
767 Z_AddField(char **ptr
, const char *field
, char *end
)
771 len
= field
? strlen (field
) + 1 : 1;
784 struct _Z_InputQ
*Z_GetFirstComplete()
786 struct _Z_InputQ
*qptr
;
796 return ((struct _Z_InputQ
*)0);
799 struct _Z_InputQ
*Z_GetNextComplete(qptr
)
800 struct _Z_InputQ
*qptr
;
809 return ((struct _Z_InputQ
*)0);
812 void Z_RemQueue(qptr
)
813 struct _Z_InputQ
*qptr
;
815 struct _Z_Hole
*hole
, *nexthole
;
818 __Q_CompleteLength
--;
820 __Q_Size
-= qptr
->msg_len
;
826 hole
= qptr
->holelist
;
828 nexthole
= hole
->next
;
833 if (qptr
== __Q_Head
&& __Q_Head
== __Q_Tail
) {
835 __Q_Head
= (struct _Z_InputQ
*)0;
836 __Q_Tail
= (struct _Z_InputQ
*)0;
840 if (qptr
== __Q_Head
) {
841 __Q_Head
= qptr
->next
;
842 __Q_Head
->prev
= (struct _Z_InputQ
*)0;
846 if (qptr
== __Q_Tail
) {
847 __Q_Tail
= qptr
->prev
;
848 __Q_Tail
->next
= (struct _Z_InputQ
*)0;
852 qptr
->prev
->next
= qptr
->next
;
853 qptr
->next
->prev
= qptr
->prev
;
858 Code_t
Z_SendFragmentedNotice(notice
, len
, cert_func
, send_func
)
861 Z_AuthProc cert_func
;
862 Z_SendProc send_func
;
864 ZNotice_t partnotice
;
867 int offset
, hdrsize
, fragsize
, ret_len
, message_len
, waitforack
;
870 hdrsize
= len
-notice
->z_message_len
;
871 fragsize
= Z_MAXPKTLEN
-hdrsize
-Z_FRAGFUDGE
;
875 waitforack
= ((notice
->z_kind
== UNACKED
|| notice
->z_kind
== ACKED
)
876 && !__Zephyr_server
);
878 partnotice
= *notice
;
880 while (offset
< notice
->z_message_len
|| !notice
->z_message_len
) {
881 (void) sprintf(multi
, "%d/%d", offset
, notice
->z_message_len
);
882 partnotice
.z_multinotice
= multi
;
884 (void) gettimeofday(&partnotice
.z_uid
.tv
,
885 (struct timezone
*)0);
886 partnotice
.z_uid
.tv
.tv_sec
=
887 htonl((unsigned long) partnotice
.z_uid
.tv
.tv_sec
);
888 partnotice
.z_uid
.tv
.tv_usec
=
889 htonl((unsigned long) partnotice
.z_uid
.tv
.tv_usec
);
890 (void) memcpy((char *)&partnotice
.z_uid
.zuid_addr
, &__My_addr
,
893 message_len
= min(notice
->z_message_len
-offset
, fragsize
);
894 partnotice
.z_message
= (char*)notice
->z_message
+offset
;
895 partnotice
.z_message_len
= message_len
;
896 if ((retval
= Z_FormatAuthHeader(&partnotice
, buffer
, Z_MAXHEADERLEN
,
897 &ret_len
, cert_func
)) != ZERR_NONE
) {
900 memcpy(buffer
+ ret_len
, partnotice
.z_message
, message_len
);
901 if ((retval
= (*send_func
)(&partnotice
, buffer
, ret_len
+message_len
,
902 waitforack
)) != ZERR_NONE
) {
906 if (!notice
->z_message_len
)
914 Code_t
Z_XmitFragment(notice
, buf
, len
, wait
)
920 return(ZSendPacket(buf
, len
, wait
));
924 /* For debugging printing */
925 const char *const ZNoticeKinds
[] = {
926 "UNSAFE", "UNACKED", "ACKED", "HMACK", "HMCTL", "SERVACK", "SERVNAK",
934 void Z_debug (const char *format
, ...)
937 if (!__Z_debug_print
)
939 va_start (pvar
, format
);
940 (*__Z_debug_print
) (format
, pvar
, __Z_debug_print_closure
);
944 void Z_debug_stderr (format
, args
, closure
)
949 vfprintf (stderr
, format
, args
);
954 int ZGetFD () { return __Zephyr_fd
; }
957 int ZQLength () { return __Q_CompleteLength
; }
960 struct sockaddr_in
ZGetDestAddr () { return __HM_addr
; }
963 Zconst
char * ZGetRealm () { return __Zephyr_realm
; }
966 void ZSetDebug(proc
, arg
)
967 void (*proc
) __P((const char *, va_list, void *));
970 __Z_debug_print
= proc
;
971 __Z_debug_print_closure
= arg
;