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.4 2000/06/25 16:01:12 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 " IP_ADDR_S " (%s)"),
55 IP_ADDR_V(cl->vpn_ip), cl->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__);
65 syslog(LOG_NOTICE, _("Connection with " IP_ADDR_S " (%s) activated"),
66 IP_ADDR_V(cl->vpn_ip), cl->hostname);
71 int send_termreq(conn_list_t *cl)
75 syslog(LOG_DEBUG, _("Sending TERMREQ to " IP_ADDR_S " (%s)"),
76 IP_ADDR_V(cl->vpn_ip), cl->hostname);
78 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
80 if(write(cl->meta_socket, buffer, buflen) < 0)
83 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
90 int send_timeout(conn_list_t *cl)
94 syslog(LOG_DEBUG, _("Sending TIMEOUT to " IP_ADDR_S " (%s)"),
95 IP_ADDR_V(cl->vpn_ip), cl->hostname);
97 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
99 if((write(cl->meta_socket, buffer, buflen)) < 0)
101 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
108 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
112 syslog(LOG_DEBUG, _("Sending DEL_HOST for " IP_ADDR_S " to " IP_ADDR_S " (%s)"),
113 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
115 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
117 if((write(cl->meta_socket, buffer, buflen)) < 0)
119 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
126 int send_ping(conn_list_t *cl)
130 syslog(LOG_DEBUG, _("Sending PING to " IP_ADDR_S " (%s)"),
131 IP_ADDR_V(cl->vpn_ip), cl->hostname);
133 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
135 if((write(cl->meta_socket, buffer, buflen)) < 0)
137 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
144 int send_pong(conn_list_t *cl)
148 syslog(LOG_DEBUG, _("Sending PONG to " IP_ADDR_S " (%s)"),
149 IP_ADDR_V(cl->vpn_ip), cl->hostname);
151 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
153 if((write(cl->meta_socket, buffer, buflen)) < 0)
155 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
162 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
168 real_ip = new_host->real_ip;
169 hostname = new_host->hostname;
170 flags = new_host->flags;
172 /* If we need to propagate information about a new host that wants us to export
173 * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
174 * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
178 if(flags & EXPORTINDIRECTDATA)
180 flags &= ~EXPORTINDIRECTDATA;
181 flags |= INDIRECTDATA;
182 real_ip = myself->vpn_ip;
183 hostname = myself->hostname;
187 syslog(LOG_DEBUG, _("Sending ADD_HOST for " IP_ADDR_S " (%s) to " IP_ADDR_S " (%s)"),
188 IP_ADDR_V(new_host->vpn_ip), hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
190 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x %d\n", ADD_HOST, new_host->real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port, flags);
192 if((write(cl->meta_socket, buffer, buflen)) < 0)
194 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
201 int send_key_changed(conn_list_t *cl, conn_list_t *src)
205 syslog(LOG_DEBUG, _("Sending KEY_CHANGED origin " IP_ADDR_S " to " IP_ADDR_S " (%s)"),
206 IP_ADDR_V(src->vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
208 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
210 if((write(cl->meta_socket, buffer, buflen)) < 0)
212 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
219 void send_key_changed_all(void)
223 for(p = conn_list; p != NULL; p = p->next)
224 if(p->status.meta && p->status.active)
225 send_key_changed(p, myself);
229 int send_basic_info(conn_list_t *cl)
233 syslog(LOG_DEBUG, _("Sending BASIC_INFO to " IP_ADDR_S),
236 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);
238 if((write(cl->meta_socket, buffer, buflen)) < 0)
240 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
247 int send_passphrase(conn_list_t *cl)
251 encrypt_passphrase(&tmp);
254 syslog(LOG_DEBUG, _("Sending PASSPHRASE to " IP_ADDR_S " (%s)"),
255 IP_ADDR_V(cl->vpn_ip), cl->hostname);
257 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
259 if((write(cl->meta_socket, buffer, buflen)) < 0)
261 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
268 int send_public_key(conn_list_t *cl)
272 syslog(LOG_DEBUG, _("Sending PUBLIC_KEY to " IP_ADDR_S " (%s)"),
273 IP_ADDR_V(cl->vpn_ip), cl->hostname);
275 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
277 if((write(cl->meta_socket, buffer, buflen)) < 0)
279 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
286 /* WDN doet deze functie? (GS)
287 int send_calculate(conn_list_t *cl, char *k)
290 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
292 if((write(cl->meta_socket, buffer, buflen)) < 0)
294 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
302 int send_key_request(ip_t to)
306 fw = lookup_conn(to);
309 syslog(LOG_ERR, _("Attempting to send REQ_KEY to " IP_ADDR_S ", which does not exist?"),
315 syslog(LOG_DEBUG, _("Sending REQ_KEY to " IP_ADDR_S " (%s)"),
316 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
318 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
320 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
322 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
325 fw->status.waitingforkey = 1;
330 int send_key_answer(conn_list_t *cl, ip_t to)
335 fw = lookup_conn(to);
339 syslog(LOG_ERR, _("Attempting to send ANS_KEY to " IP_ADDR_S ", which does not exist?"),
345 syslog(LOG_DEBUG, _("Sending ANS_KEY to " IP_ADDR_S " (%s)"),
346 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
348 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
350 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
352 syslog(LOG_ERR, _("send failed: %s:%d: %m"), __FILE__, __LINE__);
360 notify all my direct connections of a new host
361 that was added to the vpn, with the exception
362 of the source of the announcement.
364 int notify_others(conn_list_t *new, conn_list_t *source,
365 int (*function)(conn_list_t*, conn_list_t*))
369 for(p = conn_list; p != NULL; p = p->next)
370 if(p != new && p != source && p->status.meta && p->status.active)
377 notify one connection of everything
380 int notify_one(conn_list_t *new)
384 for(p = conn_list; p != NULL; p = p->next)
385 if(p != new && p->status.active)
386 send_add_host(new, p);
392 The incoming request handlers
395 int basic_info_h(conn_list_t *cl)
399 syslog(LOG_DEBUG, _("Got BASIC_INFO from " IP_ADDR_S), cl->hostname);
401 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
403 syslog(LOG_ERR, _("Got bad BASIC_INFO from " IP_ADDR_S),
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 if(setup_vpn_connection(cl) < 0)
423 if(setup_vpn_connection(cl) < 0)
431 int passphrase_h(conn_list_t *cl)
434 cl->pp = xmalloc(sizeof(*(cl->pp)));
436 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
438 syslog(LOG_ERR, _("Got bad PASSPHRASE from " IP_ADDR_S " (%s)"),
439 IP_ADDR_V(cl->vpn_ip), cl->hostname);
442 cl->pp->len = strlen(cl->pp->phrase);
445 syslog(LOG_DEBUG, _("Got PASSPHRASE from " IP_ADDR_S " (%s)"),
446 IP_ADDR_V(cl->vpn_ip), cl->hostname);
448 if(cl->status.outgoing)
456 int public_key_h(conn_list_t *cl)
461 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
463 syslog(LOG_ERR, _("Got bad PUBLIC_KEY from " IP_ADDR_S " (%s)"),
464 IP_ADDR_V(cl->vpn_ip), cl->hostname);
469 syslog(LOG_DEBUG, _("Got PUBLIC_KEY from " IP_ADDR_S " (%s)"),
470 IP_ADDR_V(cl->vpn_ip), cl->hostname);
472 if(verify_passphrase(cl, g_n))
475 syslog(LOG_ERR, _("Intruder: passphrase does not match!"));
479 if(cl->status.outgoing)
485 /* Okay, before we active the connection, we check if there is another entry
486 in the connection list with the same vpn_ip. If so, it presumably is an
487 old connection that has timed out but we don't know it yet. Because our
488 conn_list entry is not active, lookup_conn will skip ourself. */
490 while(old=lookup_conn(cl->vpn_ip))
491 terminate_connection(old);
493 cl->status.active = 1;
494 notify_others(cl, NULL, send_add_host);
501 int ack_h(conn_list_t *cl)
505 syslog(LOG_DEBUG, _("Got ACK from " IP_ADDR_S " (%s)"),
506 IP_ADDR_V(cl->vpn_ip), cl->hostname);
508 cl->status.active = 1;
509 syslog(LOG_NOTICE, _("Connection with " IP_ADDR_S " (%s) activated"),
510 IP_ADDR_V(cl->vpn_ip), cl->hostname);
515 int termreq_h(conn_list_t *cl)
518 if(!cl->status.active)
520 syslog(LOG_ERR, _("Got unauthorized TERMREQ from " IP_ADDR_S " (%s)"),
521 IP_ADDR_V(cl->vpn_ip), cl->hostname);
526 syslog(LOG_DEBUG, _("Got TERMREQ from " IP_ADDR_S " (%s)"),
527 IP_ADDR_V(cl->vpn_ip), cl->hostname);
529 cl->status.termreq = 1;
530 cl->status.active = 0;
532 if(cl->status.active)
533 notify_others(cl, NULL, send_del_host);
535 terminate_connection(cl);
540 int timeout_h(conn_list_t *cl)
543 if(!cl->status.active)
545 syslog(LOG_ERR, _("Got unauthorized TIMEOUT from " IP_ADDR_S " (%s)"),
546 IP_ADDR_V(cl->vpn_ip), cl->hostname);
551 syslog(LOG_DEBUG, _("Got TIMEOUT from " IP_ADDR_S " (%s)"),
552 IP_ADDR_V(cl->vpn_ip), cl->hostname);
554 cl->status.termreq = 1;
555 terminate_connection(cl);
560 int del_host_h(conn_list_t *cl)
565 if(!cl->status.active)
567 syslog(LOG_ERR, _("Got unauthorized DEL_HOST from " IP_ADDR_S " (%s)"),
568 IP_ADDR_V(cl->vpn_ip), cl->hostname);
572 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
574 syslog(LOG_ERR, _("Got bad DEL_HOST from " IP_ADDR_S " (%s)"),
575 IP_ADDR_V(cl->vpn_ip), cl->hostname);
580 syslog(LOG_DEBUG, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
581 IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
583 if(!(fw = lookup_conn(vpn_ip)))
585 syslog(LOG_ERR, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (%s) which does not exist?"),
586 IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
590 notify_others(cl, fw, send_del_host);
592 fw->status.termreq = 1;
593 terminate_connection(fw);
598 int ping_h(conn_list_t *cl)
601 if(!cl->status.active)
603 syslog(LOG_ERR, _("Got unauthorized PING from " IP_ADDR_S " (%s)"),
604 IP_ADDR_V(cl->vpn_ip), cl->hostname);
609 syslog(LOG_DEBUG, _("Got PING from " IP_ADDR_S " (%s)"),
610 IP_ADDR_V(cl->vpn_ip), cl->hostname);
612 cl->status.pinged = 0;
613 cl->status.got_pong = 1;
620 int pong_h(conn_list_t *cl)
623 if(!cl->status.active)
625 syslog(LOG_ERR, _("Got unauthorized PONG from " IP_ADDR_S " (%s)"),
626 IP_ADDR_V(cl->vpn_ip), cl->hostname);
631 syslog(LOG_DEBUG, _("Got PONG from " IP_ADDR_S " (%s)"),
632 IP_ADDR_V(cl->vpn_ip), cl->hostname);
634 cl->status.got_pong = 1;
639 int add_host_h(conn_list_t *cl)
646 conn_list_t *ncn, *fw;
648 if(!cl->status.active)
650 syslog(LOG_ERR, _("Got unauthorized ADD_HOST from " IP_ADDR_S " (%s)"),
651 IP_ADDR_V(cl->vpn_ip), cl->hostname);
655 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
657 syslog(LOG_ERR, _("Got bad ADD_HOST from " IP_ADDR_S " (%s)"),
658 IP_ADDR_V(cl->vpn_ip), cl->hostname);
663 syslog(LOG_DEBUG, _("Got ADD_HOST from " IP_ADDR_S " (%s)"),
664 IP_ADDR_V(cl->vpn_ip), cl->hostname);
667 Suggestion of Hans Bayle
669 if((fw = lookup_conn(vpn_ip)))
671 if(fw->nexthop == cl)
672 notify_others(fw, cl, send_add_host);
674 syslog(LOG_DEBUG, _("Invalid ADD_HOST from " IP_ADDR_S " (%s)"),
675 IP_ADDR_V(cl->vpn_ip), cl->hostname);
679 ncn = new_conn_list();
680 ncn->real_ip = real_ip;
681 ncn->hostname = hostlookup(real_ip);
682 ncn->vpn_ip = vpn_ip;
683 ncn->vpn_mask = vpn_mask;
687 ncn->next = conn_list;
689 ncn->status.active = 1;
690 notify_others(ncn, cl, send_add_host);
695 int req_key_h(conn_list_t *cl)
701 if(!cl->status.active)
703 syslog(LOG_ERR, _("Got unauthorized REQ_KEY from " IP_ADDR_S " (%s)"),
704 IP_ADDR_V(cl->vpn_ip), cl->hostname);
708 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
710 syslog(LOG_ERR, _("Got bad REQ_KEY from " IP_ADDR_S " (%s)"),
711 IP_ADDR_V(cl->vpn_ip), cl->hostname);
716 syslog(LOG_DEBUG, _("Got REQ_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
717 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
719 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
720 { /* hey! they want something from ME! :) */
721 send_key_answer(cl, from);
725 fw = lookup_conn(to);
729 syslog(LOG_ERR, _("Attempting to forward REQ_KEY to " IP_ADDR_S ", which does not exist?"),
735 syslog(LOG_DEBUG, _("Forwarding REQ_KEY to " IP_ADDR_S " (%s)"),
736 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
738 cl->buffer[cl->reqlen-1] = '\n';
740 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
742 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
749 void set_keys(conn_list_t *cl, int expiry, char *key)
755 cl->public_key = xmalloc(sizeof(*cl->key));
756 cl->public_key->key = NULL;
759 if(cl->public_key->key)
760 free(cl->public_key->key);
761 cl->public_key->length = strlen(key);
762 cl->public_key->expiry = expiry;
763 cl->public_key->key = xmalloc(cl->public_key->length + 1);
764 strcpy(cl->public_key->key, key);
766 ek = make_shared_key(key);
770 cl->key = xmalloc(sizeof(*cl->key));
777 cl->key->length = strlen(ek);
778 cl->key->expiry = expiry;
779 cl->key->key = xmalloc(cl->key->length + 1);
780 strcpy(cl->key->key, ek);
784 int ans_key_h(conn_list_t *cl)
790 conn_list_t *fw, *gk;
792 if(!cl->status.active)
794 syslog(LOG_ERR, _("Got unauthorized ANS_KEY from " IP_ADDR_S " (%s)"),
795 IP_ADDR_V(cl->vpn_ip), cl->hostname);
799 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
801 syslog(LOG_ERR, _("Got bad ANS_KEY from " IP_ADDR_S " (%s)"),
802 IP_ADDR_V(cl->vpn_ip), cl->hostname);
807 syslog(LOG_DEBUG, _("Got ANS_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
808 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
810 if(to == myself->vpn_ip)
811 { /* hey! that key's for ME! :) */
812 gk = lookup_conn(from);
816 syslog(LOG_ERR, _("Receiving ANS_KEY from " IP_ADDR_S ", which does not exist?"),
821 set_keys(gk, expiry, key);
822 gk->status.validkey = 1;
823 gk->status.waitingforkey = 0;
828 fw = lookup_conn(to);
832 syslog(LOG_ERR, _("Attempting to forward ANS_KEY to " IP_ADDR_S ", which does not exist?"),
838 syslog(LOG_DEBUG, _("Forwarding ANS_KEY to " IP_ADDR_S " (%s)"),
839 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
841 cl->buffer[cl->reqlen-1] = '\n';
843 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
845 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
852 int key_changed_h(conn_list_t *cl)
857 if(!cl->status.active)
859 syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from " IP_ADDR_S " (%s)"),
860 IP_ADDR_V(cl->vpn_ip), cl->hostname);
864 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
866 syslog(LOG_ERR, _("Got bad KEY_CHANGED from " IP_ADDR_S " (%s)"),
867 IP_ADDR_V(cl->vpn_ip), cl->hostname);
872 syslog(LOG_DEBUG, _("Got KEY_CHANGED origin " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
873 IP_ADDR_V(from), IP_ADDR_V(cl->vpn_ip), cl->hostname);
875 ik = lookup_conn(from);
879 syslog(LOG_ERR, _("Got KEY_CHANGED from " IP_ADDR_S ", which does not exist?"),
884 ik->status.validkey = 0;
885 ik->status.waitingforkey = 0;
887 notify_others(cl, ik, send_key_changed);
892 int (*request_handlers[256])(conn_list_t*) = {
893 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
894 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
895 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
896 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
897 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
898 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
899 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
900 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
901 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
902 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
903 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
904 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0