1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains functions for dumping server state between servers.
4 * Created by: John T. Kohl
6 * $Id: bdump.c,v 1.52 1999/01/22 23:19:39 ghudson Exp $
8 * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, see the file
13 #include <zephyr/mit-copyright.h>
15 #include <sys/socket.h>
19 static const char rcsid_bdump_c[] = "$Id: bdump.c,v 1.52 1999/01/22 23:19:39 ghudson Exp $";
23 * External functions are:
25 * void bdump_offer(who)
26 * strut sockaddr_in *who;
30 * void bdump_get(notice, auth, who, server)
33 * struct sockaddr_in *who;
36 * Code_t bdump_send_list_tcp(kind, port, class, inst, opcode,
37 * sender, recip, lyst, num)
38 * ZNotice_Kind_t kind;
40 * char *class, *inst, *opcode, *sender, *recip;
45 static void close_bdump __P((void* arg));
46 static Code_t bdump_send_loop __P((Server *server)),
47 bdump_ask_for __P((char *inst)),
48 bdump_recv_loop __P((Server *server));
49 static void bdump_get_v12 __P((ZNotice_t *, int, struct sockaddr_in *,
51 static Code_t get_packet __P((void *packet, int len, int *retlen));
52 static Code_t extract_sin __P((ZNotice_t *notice, struct sockaddr_in *target));
53 static Code_t send_done __P((void));
54 static Code_t send_list __P((ZNotice_Kind_t kind, int port, char *class_name,
55 char *inst, char *opcode, char *sender,
56 char *recip, char **lyst, int num));
57 static Code_t send_normal_tcp __P((ZNotice_Kind_t kind, int port,
59 char *inst, char *opcode, char *sender,
60 char *recip, char *message, int len));
61 static int net_read __P((FILE *f, char *buf, int len));
62 static int net_write __P((FILE *f, char *buf, int len));
63 static int setup_file_pointers __P((void));
64 static void shutdown_file_pointers __P((void));
65 static void cleanup __P((Server *server));
68 static long ticket_time;
69 static char my_realm[REALM_SZ];
71 #define TKTLIFETIME 120
72 #define tkt_lifetime(val) ((long) val * 5L * 60L)
75 extern C_Block serv_key;
76 extern Sched serv_ksched;
78 #endif /* HAVE_KRB4 */
80 static Timer *bdump_timer;
81 static int live_socket = -1;
82 static FILE *input, *output;
83 static struct sockaddr_in bdump_sin;
85 static int cancel_outgoing_dump;
90 extern char *bdump_version;
93 * Functions for performing a brain dump between servers.
97 * offer the brain dump to another server
102 struct sockaddr_in *who;
105 char buf[512], *addr, *lyst[2];
107 int bdump_port = IPPORT_RESERVED - 1;
108 #endif /* !HAVE_KRB4 */
110 zdbug((LOG_DEBUG, "bdump_offer"));
114 * when using HAVE_KRB4 server-server authentication, we can
115 * use any random local address
117 bdump_socket = socket(AF_INET, SOCK_STREAM, 0);
118 if (bdump_socket < 0) {
119 syslog(LOG_ERR,"bdump_offer: socket: %m");
123 memset(&bdump_sin, 0, sizeof(bdump_sin));
124 /* a port field of 0 makes the UNIX
125 * kernel choose an appropriate port/address pair */
127 bdump_sin.sin_port = 0;
128 bdump_sin.sin_addr = my_addr;
129 bdump_sin.sin_family = AF_INET;
130 retval = bind(bdump_socket, (struct sockaddr *) &bdump_sin,
133 syslog(LOG_ERR, "bdump_offer: bind: %m");
138 if (!bdump_sin.sin_port) {
139 int len = sizeof(bdump_sin);
141 if (getsockname(bdump_socket,
142 (struct sockaddr *) &bdump_sin, &len) < 0) {
143 syslog(LOG_ERR, "bdump_offer: getsockname: %m");
149 #else /* !HAVE_KRB4 */
151 * when not using HAVE_KRB4, we can't use any old port, we use
152 * Internet reserved ports instead (rresvport)
154 bdump_socket = rresvport(&bdump_port);
155 if (bdump_socket < 0) {
156 syslog(LOG_ERR,"bdump_offer: socket: %m");
160 memset(&bdump_sin, 0, sizeof(bdump_sin));
161 bdump_sin.sin_port = htons((unsigned short) bdump_port);
162 bdump_sin.sin_addr = my_addr;
163 bdump_sin.sin_family = AF_INET;
164 #endif /* HAVE_KRB4 */
166 listen(bdump_socket, 1);
168 bdump_timer = timer_set_rel(20L, close_bdump, NULL);
169 FD_SET(bdump_socket, &interesting);
170 nfds = max(bdump_socket, srv_socket) + 1;
172 addr = inet_ntoa(bdump_sin.sin_addr);
173 sprintf(buf, "%d", ntohs(bdump_sin.sin_port));
177 retval = ZSetDestAddr(who);
178 if (retval != ZERR_NONE) {
179 syslog(LOG_WARNING, "bdump_offer: ZSetDestAddr: %s",
180 error_message(retval));
184 /* myname is the hostname */
185 /* the class instance is the version number, here it is */
186 /* bdump_version, which is set in main */
187 send_list(ACKED, srv_addr.sin_port, ZEPHYR_ADMIN_CLASS, bdump_version,
188 ADMIN_BDUMP, myname, "", lyst, 2);
191 zdbug((LOG_DEBUG,"bdump_offer: address is %s/%d\n",
192 inet_ntoa(bdump_sin.sin_addr),
193 ntohs(bdump_sin.sin_port)));
199 * Accept a connection, and send the brain dump to the other server
205 struct sockaddr_in from;
208 int fromlen = sizeof(from);
210 #ifdef _POSIX_VERSION
211 struct sigaction action;
218 unsigned short fromport;
219 #endif /* HAVE_KRB4 */
222 zdbug((LOG_DEBUG, "bdump_send"));
224 /* accept the connection, and send the brain dump */
225 live_socket = accept(bdump_socket, (struct sockaddr *) &from, &fromlen);
226 if (live_socket < 0) {
227 syslog(LOG_ERR,"bdump_send: accept: %m");
230 if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *) &on,
232 syslog(LOG_WARNING, "bdump_send: setsockopt (SO_KEEPALIVE): %m");
235 fromport = ntohs(from.sin_port);
238 #ifdef _POSIX_VERSION
239 sigemptyset(&action.sa_mask);
241 action.sa_handler = SIG_IGN;
242 sigaction(SIGPIPE, &action, NULL);
245 signal(SIGPIPE, SIG_IGN); /* so we can detect failures */
248 from.sin_port = srv_addr.sin_port; /* we don't care what port
249 * it came from, and we need to
250 * fake out server_which_server() */
251 server = server_which_server(&from);
253 syslog(LOG_ERR, "bdump_send: unknown server?");
254 server = limbo_server;
257 zdbug((LOG_DEBUG, "bdump_send: connection from %s/%d",
258 inet_ntoa(from.sin_addr), ntohs(from.sin_port)));
264 if (bdump_socket >= 0) {
265 /* shut down the listening socket and the timer. */
266 FD_CLR(bdump_socket, &interesting);
268 nfds = srv_socket + 1;
270 timer_reset(bdump_timer);
273 /* Now begin the brain dump. */
276 /* receive the authenticator */
277 retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
278 SERVER_SERVICE, srvtab_file);
279 if (retval != KSUCCESS) {
280 syslog(LOG_ERR, "bdump_send: getkdata: %s",
281 krb_get_err_text(retval));
289 if (strcmp(kdata.pname, SERVER_SERVICE) ||
290 strcmp(kdata.pinst, SERVER_INSTANCE) ||
291 strcmp(kdata.prealm, ZGetRealm())) {
292 syslog(LOG_ERR, "bdump_send: peer not zephyr: %s.%s@%s",
293 kdata.pname, kdata.pinst, kdata.prealm);
297 /* authenticate back */
298 retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
301 syslog(LOG_ERR,"bdump_send: SendKerberosData: %s",
302 error_message (retval));
306 #else /* !HAVE_KRB4 */
307 if (fromport > IPPORT_RESERVED || fromport < IPPORT_RESERVED / 2) {
308 syslog(LOG_ERR, "bdump_send: bad port from peer: %d", fromport);
312 #endif /* HAVE_KRB4 */
314 retval = setup_file_pointers();
316 syslog (LOG_WARNING, "bdump_send: can't set up file pointers: %s",
317 error_message(retval));
321 retval = bdump_send_loop(server);
322 if (retval != ZERR_NONE) {
323 syslog(LOG_WARNING, "bdump_send: bdump_send_loop failed: %s",
324 error_message(retval));
328 retval = bdump_recv_loop(server);
329 if (retval != ZERR_NONE) {
330 syslog(LOG_WARNING, "bdump_send: bdump_recv_loop failed: %s",
331 error_message(retval));
336 zdbug((LOG_DEBUG, "bdump_send: finished"));
338 if (server != limbo_server) {
339 /* set this guy to be up, and schedule a hello */
340 server->state = SERV_UP;
341 timer_reset(server->timer);
342 server->timer = timer_set_rel(0L, server_timo, server);
345 zdbug((LOG_DEBUG,"cleanup sbd"));
347 shutdown_file_pointers();
349 #ifdef _POSIX_VERSION
350 action.sa_handler = SIG_DFL;
351 sigaction(SIGPIPE, &action, NULL);
353 signal(SIGPIPE, SIG_DFL);
357 /* Now that we are finished dumping, send all the queued packets */
358 server_send_queue(server);
364 bdump_get_v12 (notice, auth, who, server)
367 struct sockaddr_in *who;
370 struct sockaddr_in from;
373 #ifdef _POSIX_VERSION
374 struct sigaction action;
379 #else /* !HAVE_KRB4 */
380 int reserved_port = IPPORT_RESERVED - 1;
381 #endif /* HAVE_KRB4 */
386 #ifdef _POSIX_VERSION
388 sigemptyset(&action.sa_mask);
389 action.sa_handler = SIG_IGN;
390 sigaction(SIGPIPE, &action, NULL);
392 signal(SIGPIPE, SIG_IGN); /* so we can detect problems */
393 #endif /* _POSIX_VRESION */
395 if (bdump_socket >= 0) {
396 /* We cannot go get a brain dump when someone may
397 potentially be connecting to us (if that other
398 server is the server to whom we are connecting,
399 we will deadlock. so we shut down the listening
400 socket and the timer. */
401 FD_CLR(bdump_socket, &interesting);
405 timer_reset(bdump_timer);
408 retval = extract_sin(notice, &from);
409 if (retval != ZERR_NONE) {
410 syslog(LOG_ERR, "bdump_get: sin: %s", error_message(retval));
411 #ifdef _POSIX_VERSION
412 action.sa_handler = SIG_DFL;
413 sigaction(SIGPIPE, &action, NULL);
415 signal(SIGPIPE, SIG_DFL);
422 if (ntohs(from.sin_port) > IPPORT_RESERVED ||
423 ntohs(from.sin_port) < IPPORT_RESERVED / 2) {
424 syslog(LOG_ERR, "bdump_get: port not reserved: %d",
425 ntohs(from.sin_port));
429 live_socket = rresvport(&reserved_port);
430 #else /* !HAVE_KRB4 */
431 live_socket = socket(AF_INET, SOCK_STREAM, 0);
432 #endif /* HAVE_KRB4 */
433 if (live_socket < 0) {
434 syslog(LOG_ERR, "bdump_get: socket: %m");
438 if (connect(live_socket, (struct sockaddr *) &from, sizeof(from))) {
439 syslog(LOG_ERR, "bdump_get: connect: %m");
443 if (setsockopt(live_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
445 syslog(LOG_WARNING, "bdump_get: setsockopt (SO_KEEPALIVE): %m");
447 zdbug((LOG_DEBUG, "bdump_get: connected"));
450 /* Now begin the brain dump. */
453 /* send an authenticator */
458 retval = SendKerberosData(live_socket, &ticket, SERVER_SERVICE,
461 syslog(LOG_ERR,"bdump_get: %s", error_message(retval));
466 zdbug((LOG_DEBUG, "bdump_get: SendKerberosData ok"));
469 /* get his authenticator */
470 retval = GetKerberosData(live_socket, from.sin_addr, &kdata,
471 SERVER_SERVICE, srvtab_file);
472 if (retval != KSUCCESS) {
473 syslog(LOG_ERR, "bdump_get getkdata: %s",krb_get_err_text(retval));
477 /* my_realm is filled in inside get_tgt() */
478 if (strcmp(kdata.pname, SERVER_SERVICE) ||
479 strcmp(kdata.pinst, SERVER_INSTANCE) ||
480 strcmp(kdata.prealm, my_realm)) {
481 syslog(LOG_ERR, "bdump_get: peer not zephyr in lrealm: %s.%s@%s",
482 kdata.pname, kdata.pinst,kdata.prealm);
486 #endif /* HAVE_KRB4 */
487 retval = setup_file_pointers();
489 syslog(LOG_WARNING, "bdump_get: can't set up file pointers: %s",
490 error_message (retval));
494 retval = bdump_recv_loop(server);
495 if (retval != ZERR_NONE) {
496 syslog(LOG_WARNING, "bdump_get: bdump_recv_loop failed: %s",
497 error_message(retval));
502 zdbug((LOG_DEBUG,"bdump_get: gbdl ok"));
504 retval = bdump_send_loop(server);
505 if (retval != ZERR_NONE) {
506 syslog(LOG_WARNING, "bdump_send_loop failed: %s",
507 error_message(retval));
512 zdbug((LOG_DEBUG, "bdump_get: gbd finished"));
514 /* set this guy to be up, and schedule a hello */
515 server->state = SERV_UP;
516 timer_reset(server->timer);
517 server->timer = timer_set_rel(0L, server_timo, server);
520 zdbug((LOG_DEBUG,"cleanup gbd"));
522 shutdown_file_pointers();
523 #ifdef _POSIX_VERSION
524 action.sa_handler = SIG_DFL;
525 sigaction(SIGPIPE, &action, NULL);
527 signal(SIGPIPE, SIG_DFL);
531 /* Now that we are finished dumping, send all the queued packets */
532 server_send_queue(server);
538 bdump_get(notice, auth, who, server)
541 struct sockaddr_in *who;
544 void (*proc) __P((ZNotice_t *, int, struct sockaddr_in *, Server *));
550 syslog(LOG_DEBUG, "bdump_get: bdump v%s avail %s",
551 notice->z_class_inst, inet_ntoa(who->sin_addr));
554 if (strcmp (notice->z_class_inst, "1.2") == 0)
555 proc = bdump_get_v12;
558 (*proc)(notice, auth, who, server);
561 "bdump_get: Incompatible bdump version '%s' from %s",
562 notice->z_class_inst,
563 inet_ntoa(who->sin_addr));
568 * Send a list off as the specified notice
572 bdump_send_list_tcp(kind, addr, class_name, inst, opcode, sender, recip, lyst,
575 struct sockaddr_in *addr;
577 char *class_name, *inst, *opcode, *sender, *recip, **lyst;
580 char *pack, addrbuf[100];
585 retval = ZMakeAscii(addrbuf, sizeof(addrbuf),
586 (unsigned char *) &addr->sin_addr,
587 sizeof(struct in_addr));
588 if (retval != ZERR_NONE)
590 notice.z_kind = kind;
592 notice.z_port = addr->sin_port;
593 notice.z_class = class_name;
594 notice.z_class_inst = inst;
595 notice.z_opcode = opcode;
596 notice.z_sender = sender;
597 notice.z_recipient = recip;
598 notice.z_default_format = "";
599 notice.z_num_other_fields = 1;
600 notice.z_other_fields[0] = addrbuf;
602 retval = ZFormatNoticeList(¬ice, lyst, num, &pack, &packlen, ZNOAUTH);
603 if (retval != ZERR_NONE)
606 length = htons((u_short) packlen);
608 count = net_write(output, (char *) &length, sizeof(length));
609 if (count != sizeof(length)) {
614 syslog(LOG_WARNING, "slt (length) xmit: %d vs %d",
615 sizeof(length), count);
617 return(ZSRV_PKSHORT);
621 count = net_write(output, pack, packlen);
622 if (count != packlen) {
627 syslog(LOG_WARNING, "slt (packet) xmit: %d vs %d",
630 return(ZSRV_PKSHORT);
638 shutdown_file_pointers() {
647 if (live_socket >= 0) {
657 #ifdef _POSIX_VERSION
658 struct sigaction action;
662 zdbug((LOG_DEBUG, "bdump cleanup"));
664 if (server != limbo_server) {
665 server->state = SERV_DEAD;
666 timer_reset(server->timer);
667 server->timer = timer_set_rel(0L, server_timo, server);
669 shutdown_file_pointers ();
670 #ifdef _POSIX_VERSION
672 sigemptyset(&action.sa_mask);
673 action.sa_handler = SIG_DFL;
674 sigaction(SIGPIPE,&action, NULL);
676 signal(SIGPIPE, SIG_DFL);
677 #endif /* _POSIX_VERSION */
686 /* MIT Kerberos 4 get_svc_in_tkt() requires instance to be writable and
687 * at least INST_SZ bytes long. */
688 static char buf[INST_SZ + 1] = SERVER_INSTANCE;
696 retval = krb_get_lrealm(my_realm, 1);
697 if (retval != KSUCCESS) {
698 syslog(LOG_ERR,"krb_get_lrealm: %s", krb_get_err_text(retval));
703 /* have they expired ? */
704 if (ticket_time < NOW - tkt_lifetime(TKTLIFETIME) + 15L) {
707 zdbug((LOG_DEBUG,"get new tickets: %d %d %d", ticket_time, NOW,
708 NOW - tkt_lifetime(TKTLIFETIME) + 15L));
712 retval = krb_get_svc_in_tkt(SERVER_SERVICE, buf, ZGetRealm(),
713 "krbtgt", ZGetRealm(),
714 TKTLIFETIME, srvtab_file);
715 if (retval != KSUCCESS) {
716 syslog(LOG_ERR,"get_tgt: krb_get_svc_in_tkt: %s",
717 krb_get_err_text(retval));
725 retval = read_service_key(SERVER_SERVICE, SERVER_INSTANCE,
726 ZGetRealm(), 0 /*kvno*/,
727 srvtab_file, serv_key);
728 if (retval != KSUCCESS) {
729 syslog(LOG_ERR, "get_tgt: read_service_key: %s",
730 krb_get_err_text(retval));
733 s = (Sched *) check_key_sched_cache(serv_key);
737 des_key_sched(serv_key, serv_ksched.s);
738 add_to_key_sched_cache(serv_key, &serv_ksched);
740 #endif /* !NOENCRYPTION */
744 #endif /* HAVE_KRB4 */
747 * The braindump offer wasn't taken, so we retract it.
755 if (bdump_socket >= 0) {
756 FD_CLR(bdump_socket, &interesting);
758 nfds = srv_socket + 1;
761 zdbug((LOG_DEBUG, "bdump not used"));
765 zdbug((LOG_DEBUG, "bdump not open"));
772 * Start receiving instruction notices from the brain dump socket
776 bdump_recv_loop(server)
783 Client *client = NULL;
784 struct sockaddr_in who;
788 #endif /* HAVE_KRB4 */
792 zdbug((LOG_DEBUG, "bdump recv loop"));
795 /* do the inverse of bdump_send_loop, registering stuff on the fly */
797 if (packets_waiting()) {
798 /* A non-braindump packet is waiting; handle it. */
800 bdump_concurrent = 1;
802 bdump_concurrent = 0;
805 len = sizeof(packet);
806 retval = get_packet(packet, len, &len);
807 if (retval != ZERR_NONE) {
808 syslog(LOG_ERR, "brl get pkt: %s", error_message(retval));
812 retval = ZParseNotice(packet, len, ¬ice);
813 if (retval != ZERR_NONE) {
814 syslog(LOG_ERR, "brl notice parse: %s", error_message(retval));
821 sprintf(buf, "bdump:%s '%s' '%s' '%s' '%s' '%s'",
822 ZNoticeKinds[(int) notice.z_kind], notice.z_class,
823 notice.z_class_inst, notice.z_opcode, notice.z_sender,
825 syslog(LOG_DEBUG, buf);
828 if (notice.z_num_other_fields >= 1) {
829 retval = ZReadAscii(notice.z_other_fields[0],
830 strlen(notice.z_other_fields[0]),
831 (unsigned char *) &who.sin_addr,
832 sizeof(struct in_addr));
833 if (retval != ZERR_NONE) {
834 syslog(LOG_ERR, "brl zreadascii failed: %s",
835 error_message(retval));
839 who.sin_addr.s_addr = notice.z_sender_addr.s_addr;
841 who.sin_family = AF_INET;
842 who.sin_port = notice.z_port;
844 if (strcmp(notice.z_opcode, ADMIN_DONE) == 0) {
845 /* end of brain dump */
847 } else if (strcmp(notice.z_opcode, ADMIN_NEWREALM) == 0) {
848 /* get a realm from the message */
849 realm = realm_get_realm_by_name(notice.z_message);
852 } else if (strcmp(notice.z_class, LOGIN_CLASS) == 0) {
853 /* 1 = tell it we are authentic */
854 retval = ulogin_dispatch(¬ice, 1, &who, server);
855 if (retval != ZERR_NONE) {
856 syslog(LOG_ERR, "brl ul_disp failed: %s",
857 error_message(retval));
860 } else if (strcmp(notice.z_opcode, ADMIN_NEWCLT) == 0) {
862 notice.z_port = htons((u_short) atoi(notice.z_message));
863 retval = client_register(¬ice, &who.sin_addr, &client, 0);
864 if (retval != ZERR_NONE) {
865 syslog(LOG_ERR,"brl failed: %s", error_message(retval));
869 memset(client->session_key, 0, sizeof(C_Block));
870 if (*notice.z_class_inst) {
871 /* a C_Block is there */
872 cp = notice.z_message + strlen(notice.z_message) + 1;
873 retval = ZReadAscii(cp, strlen(cp), cblock, sizeof(C_Block));
874 if (retval != ZERR_NONE) {
875 syslog(LOG_ERR,"brl bad cblk read: %s (%s)",
876 error_message(retval), cp);
879 memcpy(cblock, client->session_key, sizeof(C_Block));
881 des_ecb_encrypt(cblock, client->session_key, serv_ksched.s,
886 #endif /* HAVE_KRB4 */
887 } else if (strcmp(notice.z_opcode, CLIENT_SUBSCRIBE) == 0) {
888 /* a subscription packet */
890 syslog(LOG_ERR, "brl no client");
893 retval = subscr_subscribe(client, ¬ice);
894 if (retval != ZERR_NONE) {
895 syslog(LOG_WARNING, "brl subscr failed: %s",
896 error_message(retval));
899 } else if (strcmp(notice.z_opcode, REALM_SUBSCRIBE) == 0) {
900 /* add a subscription for a realm */
902 syslog(LOG_ERR, "brl no realm");
905 retval = subscr_realm(realm, ¬ice);
906 if (retval != ZERR_NONE) {
907 syslog(LOG_WARNING, "brl subscr failed: %s",
908 error_message(retval));
912 syslog(LOG_ERR, "brl bad opcode %s",notice.z_opcode);
913 return ZSRV_UNKNOWNOPCODE;
919 * Send all the state to the peer.
923 bdump_send_loop(server)
929 zdbug((LOG_DEBUG, "bdump send loop"));
932 retval = uloc_send_locations();
933 if (retval != ZERR_NONE)
935 retval = client_send_clients();
936 if (retval != ZERR_NONE)
938 retval = realm_send_realms();
939 if (retval != ZERR_NONE)
945 * Send a sync indicating end of this host
954 zdbug((LOG_DEBUG, "send_done"));
956 retval = send_normal_tcp(SERVACK, bdump_sin.sin_port, ZEPHYR_ADMIN_CLASS,
957 "", ADMIN_DONE, myname, "", NULL, 0);
963 * Send a list off as the specified notice
967 send_list(kind, port, class_name, inst, opcode, sender, recip, lyst, num)
970 char *class_name, *inst, *opcode, *sender, *recip, **lyst;
977 notice.z_kind = kind;
978 notice.z_port = port;
979 notice.z_class = class_name;
980 notice.z_class_inst = inst;
981 notice.z_opcode = opcode;
982 notice.z_sender = sender;
983 notice.z_recipient = recip;
984 notice.z_default_format = "";
985 notice.z_num_other_fields = 0;
987 retval = ZFormatNoticeList(¬ice, lyst, num, &pack, &packlen, ZNOAUTH);
988 if (retval != ZERR_NONE) {
989 syslog(LOG_WARNING, "sl format: %s", error_message(retval));
993 retval = ZSendPacket(pack, packlen, 0);
994 if (retval != ZERR_NONE)
995 syslog(LOG_WARNING, "sl xmit: %s", error_message(retval));
1001 * Send a message off as the specified notice, via TCP
1005 send_normal_tcp(kind, port, class_name, inst, opcode, sender, recip,
1007 ZNotice_Kind_t kind;
1009 char *class_name, *inst, *opcode, *sender, *recip, *message;
1017 notice.z_kind = kind;
1018 notice.z_port = port;
1019 notice.z_class = class_name;
1020 notice.z_class_inst = inst;
1021 notice.z_opcode = opcode;
1022 notice.z_sender = sender;
1023 notice.z_recipient = recip;
1024 notice.z_default_format = "";
1025 notice.z_message = message;
1026 notice.z_message_len = len;
1027 notice.z_num_other_fields = 0;
1029 retval = ZFormatNotice(¬ice, &pack, &packlen, ZNOAUTH);
1030 if (retval != ZERR_NONE) {
1031 syslog(LOG_WARNING, "sn format: %s", error_message(retval));
1035 length = htons((u_short) packlen);
1037 count = net_write(output, (char *) &length, sizeof(length));
1038 if (count != sizeof(length)) {
1040 syslog(LOG_WARNING, "snt xmit/len: %m");
1044 syslog(LOG_WARNING, "snt xmit: %d vs %d",sizeof(length),count);
1049 count = net_write(output, pack, packlen);
1050 if (count != packlen) {
1052 syslog(LOG_WARNING, "snt xmit: %m");
1056 syslog(LOG_WARNING, "snt xmit: %d vs %d",packlen, count);
1066 * get a packet from the TCP socket
1067 * return 0 if successful, error code else
1071 get_packet(packet, len, retlen)
1079 result = net_read(input, (char *) &length, sizeof(u_short));
1080 if (result < sizeof(short)) {
1084 syslog(LOG_ERR, "get_pkt len: %d vs %d (%m)", result,
1090 length = ntohs(length);
1092 return ZSRV_BUFSHORT;
1093 result = net_read(input, packet, (int) length);
1094 if (result < length) {
1098 syslog(LOG_ERR, "get_pkt: %d vs %d (%m)", result, length);
1107 extract_sin(notice, target)
1109 struct sockaddr_in *target;
1111 char *cp = notice->z_message;
1115 if (!notice->z_message_len || *buf == '\0') {
1117 zdbug((LOG_DEBUG,"no addr"));
1119 return ZSRV_PKSHORT;
1121 target->sin_addr.s_addr = inet_addr(cp);
1123 cp += (strlen(cp) + 1); /* past the null */
1124 if ((cp >= notice->z_message + notice->z_message_len) || (*cp == '\0')) {
1126 zdbug((LOG_DEBUG, "no port"));
1128 return(ZSRV_PKSHORT);
1130 target->sin_port = htons((u_short) atoi(cp));
1131 target->sin_family = AF_INET;
1136 net_read(f, buf, len)
1146 cc = fread(buf, 1, len, f);
1157 net_write(f, buf, len)
1165 cc = fwrite (buf, 1, wrlen, f);
1170 } while (wrlen > 0);
1175 setup_file_pointers ()
1179 input = fdopen (live_socket, "r");
1183 fd = dup (live_socket);
1186 output = fdopen (fd, "w");