2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000 Guus Sliepen <guus@sliepen.warande.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: protocol.c,v 1.28.4.18 2000/06/30 12:41:06 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
45 char buffer[MAXBUFSIZE+1];
48 /* Outgoing request routines */
50 int send_ack(conn_list_t *cl)
54 syslog(LOG_DEBUG, _("Sending ACK to %s (%s)"),
55 cl->vpn_hostname, cl->real_hostname);
57 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
59 if((write(cl->meta_socket, buffer, buflen)) < 0)
61 syslog(LOG_ERR, _("Send failed: %d:%d: %m"), __FILE__, __LINE__);
68 int send_termreq(conn_list_t *cl)
72 syslog(LOG_DEBUG, _("Sending TERMREQ to %s (%s)"),
73 cl->vpn_hostname, cl->real_hostname);
75 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
77 if(write(cl->meta_socket, buffer, buflen) < 0)
80 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
87 int send_timeout(conn_list_t *cl)
91 syslog(LOG_DEBUG, _("Sending TIMEOUT to %s (%s)"),
92 cl->vpn_hostname, cl->real_hostname);
94 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
96 if((write(cl->meta_socket, buffer, buflen)) < 0)
98 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
105 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
109 syslog(LOG_DEBUG, _("Sending DEL_HOST for %s (%s) to %s (%s)"),
110 new_host->vpn_hostname, new_host->real_hostname, cl->vpn_hostname, cl->real_hostname);
112 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
114 if((write(cl->meta_socket, buffer, buflen)) < 0)
116 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
123 int send_ping(conn_list_t *cl)
127 syslog(LOG_DEBUG, _("Sending PING to %s (%s)"),
128 cl->vpn_hostname, cl->real_hostname);
130 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
132 if((write(cl->meta_socket, buffer, buflen)) < 0)
134 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
141 int send_pong(conn_list_t *cl)
145 syslog(LOG_DEBUG, _("Sending PONG to %s (%s)"),
146 cl->vpn_hostname, cl->real_hostname);
148 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
150 if((write(cl->meta_socket, buffer, buflen)) < 0)
152 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
159 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
165 real_ip = new_host->real_ip;
166 hostname = new_host->real_hostname;
167 flags = new_host->flags;
169 /* If we need to propagate information about a new host that wants us to export
170 * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
171 * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
175 if(flags & EXPORTINDIRECTDATA)
177 flags &= ~EXPORTINDIRECTDATA;
178 flags |= INDIRECTDATA;
179 real_ip = myself->vpn_ip;
180 hostname = myself->real_hostname;
184 syslog(LOG_DEBUG, _("Sending ADD_HOST for %s (%s) to %s (%s)"),
185 new_host->vpn_hostname, hostname, cl->vpn_hostname, cl->real_hostname);
187 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x %d\n", ADD_HOST, real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port, flags);
189 if((write(cl->meta_socket, buffer, buflen)) < 0)
191 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
198 int send_key_changed(conn_list_t *cl, conn_list_t *src)
202 syslog(LOG_DEBUG, _("Sending KEY_CHANGED origin %s to %s (%s)"),
203 src->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
205 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
207 if((write(cl->meta_socket, buffer, buflen)) < 0)
209 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
216 void send_key_changed_all(void)
220 for(p = conn_list; p != NULL; p = p->next)
221 if(p->status.meta && p->status.active)
222 send_key_changed(p, myself);
226 int send_basic_info(conn_list_t *cl)
230 syslog(LOG_DEBUG, _("Sending BASIC_INFO to %s"),
233 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x %d\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port, myself->flags);
235 if((write(cl->meta_socket, buffer, buflen)) < 0)
237 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
244 int send_passphrase(conn_list_t *cl)
248 encrypt_passphrase(&tmp);
251 syslog(LOG_DEBUG, _("Sending PASSPHRASE to %s (%s)"),
252 cl->vpn_hostname, cl->real_hostname);
254 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
256 if((write(cl->meta_socket, buffer, buflen)) < 0)
258 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
265 int send_public_key(conn_list_t *cl)
269 syslog(LOG_DEBUG, _("Sending PUBLIC_KEY to %s (%s)"),
270 cl->vpn_hostname, cl->real_hostname);
272 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
274 if((write(cl->meta_socket, buffer, buflen)) < 0)
276 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
283 /* WDN doet deze functie? (GS)
284 int send_calculate(conn_list_t *cl, char *k)
287 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
289 if((write(cl->meta_socket, buffer, buflen)) < 0)
291 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
299 int send_key_request(ip_t to)
303 fw = lookup_conn(to);
306 syslog(LOG_ERR, _("Attempting to send REQ_KEY to %d.%d.%d.%d, which does not exist?"),
312 syslog(LOG_DEBUG, _("Sending REQ_KEY to %s (%s)"),
313 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
315 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
317 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
319 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
322 fw->status.waitingforkey = 1;
327 int send_key_answer(conn_list_t *cl, ip_t to)
332 fw = lookup_conn(to);
336 syslog(LOG_ERR, _("Attempting to send ANS_KEY to %d.%d.%d.%d, which does not exist?"),
342 syslog(LOG_DEBUG, _("Sending ANS_KEY to %s (%s)"),
343 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
345 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
347 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
349 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
357 notify all my direct connections of a new host
358 that was added to the vpn, with the exception
359 of the source of the announcement.
361 int notify_others(conn_list_t *new, conn_list_t *source,
362 int (*function)(conn_list_t*, conn_list_t*))
366 for(p = conn_list; p != NULL; p = p->next)
367 if(p != new && p != source && p->status.meta && p->status.active)
374 notify one connection of everything
377 int notify_one(conn_list_t *new)
381 for(p = conn_list; p != NULL; p = p->next)
382 if(p != new && p->status.active)
383 send_add_host(new, p);
389 The incoming request handlers
392 int basic_info_h(conn_list_t *cl)
397 syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->real_hostname);
399 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
401 syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
406 cl->vpn_hostname = hostlookup(htonl(cl->vpn_ip));
408 if(cl->protocol_version != PROT_CURRENT)
410 syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
411 cl->protocol_version);
415 if(cl->status.outgoing)
417 /* First check if the host we connected to is already in our
418 connection list. If so, we are probably making a loop, which
422 if(old=lookup_conn(cl->vpn_ip))
425 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"),
426 cl->vpn_hostname, cl->real_hostname);
427 cl->status.outgoing = 0;
428 old->status.outgoing = 1;
429 terminate_connection(cl);
433 if(setup_vpn_connection(cl) < 0)
440 if(setup_vpn_connection(cl) < 0)
448 int passphrase_h(conn_list_t *cl)
451 cl->pp = xmalloc(sizeof(*(cl->pp)));
453 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
455 syslog(LOG_ERR, _("Got bad PASSPHRASE from %s (%s)"),
456 cl->vpn_hostname, cl->real_hostname);
459 cl->pp->len = strlen(cl->pp->phrase);
462 syslog(LOG_DEBUG, _("Got PASSPHRASE from %s (%s)"),
463 cl->vpn_hostname, cl->real_hostname);
465 if(cl->status.outgoing)
473 int public_key_h(conn_list_t *cl)
478 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
480 syslog(LOG_ERR, _("Got bad PUBLIC_KEY from %s (%s)"),
481 cl->vpn_hostname, cl->real_hostname);
486 syslog(LOG_DEBUG, _("Got PUBLIC_KEY from %s (%s)"),
487 cl->vpn_hostname, cl->real_hostname);
489 if(verify_passphrase(cl, g_n))
492 syslog(LOG_ERR, _("Intruder from %s: passphrase for %s does not match!"),
493 cl->real_hostname, cl->vpn_hostname);
497 if(cl->status.outgoing)
503 /* Okay, before we active the connection, we check if there is another entry
504 in the connection list with the same vpn_ip. If so, it presumably is an
505 old connection that has timed out but we don't know it yet.
508 while(old = lookup_conn(cl->vpn_ip))
510 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
511 cl->vpn_hostname, old->real_hostname, cl->real_hostname);
512 old->status.active = 0;
513 terminate_connection(old);
516 cl->status.active = 1;
519 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
520 cl->vpn_hostname, cl->real_hostname);
522 notify_others(cl, NULL, send_add_host);
529 int ack_h(conn_list_t *cl)
533 syslog(LOG_DEBUG, _("Got ACK from %s (%s)"),
534 cl->vpn_hostname, cl->real_hostname);
536 cl->status.active = 1;
538 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
539 cl->vpn_hostname, cl->real_hostname);
541 notify_others(cl, NULL, send_add_host);
549 int termreq_h(conn_list_t *cl)
552 if(!cl->status.active)
554 syslog(LOG_ERR, _("Got unauthorized TERMREQ from %s (%s)"),
555 cl->vpn_hostname, cl->real_hostname);
560 syslog(LOG_DEBUG, _("Got TERMREQ from %s (%s)"),
561 cl->vpn_hostname, cl->real_hostname);
563 cl->status.termreq = 1;
565 terminate_connection(cl);
570 int timeout_h(conn_list_t *cl)
573 if(!cl->status.active)
575 syslog(LOG_ERR, _("Got unauthorized TIMEOUT from %s (%s)"),
576 cl->vpn_hostname, cl->real_hostname);
581 syslog(LOG_DEBUG, _("Got TIMEOUT from %s (%s)"),
582 cl->vpn_hostname, cl->real_hostname);
584 cl->status.termreq = 1;
585 terminate_connection(cl);
590 int del_host_h(conn_list_t *cl)
595 if(!cl->status.active)
597 syslog(LOG_ERR, _("Got unauthorized DEL_HOST from %s (%s)"),
598 cl->vpn_hostname, cl->real_hostname);
602 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
604 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
605 cl->vpn_hostname, cl->real_hostname);
609 if(!(fw = lookup_conn(vpn_ip)))
611 syslog(LOG_ERR, _("Got DEL_HOST for %d.%d.%d.%d from %s (%s) which does not exist?"),
612 IP_ADDR_V(vpn_ip), cl->vpn_hostname, cl->real_hostname);
616 /* Connections lists are really messed up if this happens */
617 if(vpn_ip == myself->vpn_ip)
619 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
620 cl->vpn_hostname, cl->real_hostname);
626 syslog(LOG_DEBUG, _("Got DEL_HOST for %s (%s) from %s (%s)"),
627 fw->vpn_hostname, fw->real_hostname, cl->vpn_hostname, cl->real_hostname);
629 notify_others(fw, cl, send_del_host);
631 fw->status.termreq = 1;
632 fw->status.active = 0;
634 terminate_connection(fw);
639 int ping_h(conn_list_t *cl)
642 if(!cl->status.active)
644 syslog(LOG_ERR, _("Got unauthorized PING from %s (%s)"),
645 cl->vpn_hostname, cl->real_hostname);
650 syslog(LOG_DEBUG, _("Got PING from %s (%s)"),
651 cl->vpn_hostname, cl->real_hostname);
653 cl->status.pinged = 0;
654 cl->status.got_pong = 1;
661 int pong_h(conn_list_t *cl)
664 if(!cl->status.active)
666 syslog(LOG_ERR, _("Got unauthorized PONG from %s (%s)"),
667 cl->vpn_hostname, cl->real_hostname);
672 syslog(LOG_DEBUG, _("Got PONG from %s (%s)"),
673 cl->vpn_hostname, cl->real_hostname);
675 cl->status.got_pong = 1;
680 int add_host_h(conn_list_t *cl)
687 conn_list_t *ncn, *old;
689 if(!cl->status.active)
691 syslog(LOG_ERR, _("Got unauthorized ADD_HOST from %s (%s)"),
692 cl->vpn_hostname, cl->real_hostname);
696 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
698 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"),
699 cl->vpn_hostname, cl->real_hostname);
703 if(old = lookup_conn(vpn_ip))
705 if((real_ip==old->real_ip) && (vpn_mask==old->vpn_mask) && (port==old->port))
708 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
709 old->vpn_hostname, old->real_hostname, cl->vpn_hostname, cl->real_hostname);
710 goto skip_add_host; /* One goto a day keeps the deeply nested if constructions away. */
715 syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
716 old->vpn_hostname, old->real_hostname);
717 old->status.active = 0;
718 terminate_connection(old);
722 /* Connections lists are really messed up if this happens */
723 if(vpn_ip == myself->vpn_ip)
725 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"),
726 cl->vpn_hostname, cl->real_hostname);
731 ncn = new_conn_list();
732 ncn->real_ip = real_ip;
733 ncn->real_hostname = hostlookup(htonl(real_ip));
734 ncn->vpn_ip = vpn_ip;
735 ncn->vpn_mask = vpn_mask;
736 ncn->vpn_hostname = hostlookup(htonl(vpn_ip));
740 ncn->next = conn_list;
742 ncn->status.active = 1;
745 syslog(LOG_DEBUG, _("Got ADD_HOST for %s (%s) from %s (%s)"),
746 ncn->vpn_hostname, ncn->real_hostname, cl->vpn_hostname, cl->real_hostname);
750 notify_others(ncn, cl, send_add_host);
755 int req_key_h(conn_list_t *cl)
761 if(!cl->status.active)
763 syslog(LOG_ERR, _("Got unauthorized REQ_KEY from %s (%s)"),
764 cl->vpn_hostname, cl->real_hostname);
768 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
770 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
771 cl->vpn_hostname, cl->real_hostname);
776 syslog(LOG_DEBUG, _("Got REQ_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
777 IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
779 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
780 { /* hey! they want something from ME! :) */
781 send_key_answer(cl, from);
785 fw = lookup_conn(to);
789 syslog(LOG_ERR, _("Attempting to forward REQ_KEY to %d.%d.%d.%d, which does not exist?"),
795 syslog(LOG_DEBUG, _("Forwarding REQ_KEY to %s (%s)"),
796 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
798 cl->buffer[cl->reqlen-1] = '\n';
800 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
802 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
809 void set_keys(conn_list_t *cl, int expiry, char *key)
815 cl->public_key = xmalloc(sizeof(*cl->key));
816 cl->public_key->key = NULL;
819 if(cl->public_key->key)
820 free(cl->public_key->key);
821 cl->public_key->length = strlen(key);
822 cl->public_key->expiry = expiry;
823 cl->public_key->key = xmalloc(cl->public_key->length + 1);
824 strcpy(cl->public_key->key, key);
826 ek = make_shared_key(key);
830 cl->key = xmalloc(sizeof(*cl->key));
837 cl->key->length = strlen(ek);
838 cl->key->expiry = expiry;
839 cl->key->key = xmalloc(cl->key->length + 1);
840 strcpy(cl->key->key, ek);
844 int ans_key_h(conn_list_t *cl)
850 conn_list_t *fw, *gk;
852 if(!cl->status.active)
854 syslog(LOG_ERR, _("Got unauthorized ANS_KEY from %s (%s)"),
855 cl->vpn_hostname, cl->real_hostname);
859 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
861 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
862 cl->vpn_hostname, cl->real_hostname);
867 syslog(LOG_DEBUG, _("Got ANS_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
868 IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
870 if(to == myself->vpn_ip)
871 { /* hey! that key's for ME! :) */
872 gk = lookup_conn(from);
876 syslog(LOG_ERR, _("Receiving ANS_KEY origin %d.%d.%d.%d from %s (%s), which does not exist?"),
877 IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
881 set_keys(gk, expiry, key);
882 gk->status.validkey = 1;
883 gk->status.waitingforkey = 0;
888 fw = lookup_conn(to);
892 syslog(LOG_ERR, _("Attempting to forward ANS_KEY to %d.%d.%d.%d, which does not exist?"),
898 syslog(LOG_DEBUG, _("Forwarding ANS_KEY to %s (%s)"),
899 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
901 cl->buffer[cl->reqlen-1] = '\n';
903 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
905 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
912 int key_changed_h(conn_list_t *cl)
917 if(!cl->status.active)
919 syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from %s (%s)"),
920 cl->vpn_hostname, cl->real_hostname);
924 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
926 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
927 cl->vpn_hostname, cl->real_hostname);
931 ik = lookup_conn(from);
935 syslog(LOG_ERR, _("Got KEY_CHANGED origin %d.%d.%d.%d from %s (%s), which does not exist?"),
936 IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
941 syslog(LOG_DEBUG, _("Got KEY_CHANGED origin %s from %s (%s)"),
942 ik->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
944 ik->status.validkey = 0;
945 ik->status.waitingforkey = 0;
947 notify_others(ik, cl, send_key_changed);
952 int (*request_handlers[256])(conn_list_t*) = {
953 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
954 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
955 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
956 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
957 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
958 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
959 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
960 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0