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.8 2000/06/26 19:39:34 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, 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 %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 %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 %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 Suggestion of Hans Bayle
665 if((fw = lookup_conn(vpn_ip)))
667 if(fw->nexthop == cl)
668 notify_others(fw, cl, send_add_host);
670 syslog(LOG_DEBUG, _("Invalid ADD_HOST from " IP_ADDR_S " (%s)"),
671 IP_ADDR_V(cl->vpn_ip), cl->hostname);
675 ncn = new_conn_list();
676 ncn->real_ip = real_ip;
677 ncn->hostname = hostlookup(htonl(real_ip));
678 ncn->vpn_ip = vpn_ip;
679 ncn->vpn_mask = vpn_mask;
683 ncn->next = conn_list;
685 ncn->status.active = 1;
688 syslog(LOG_DEBUG, _("Got ADD_HOST for " IP_ADDR_S " (%s) from " IP_ADDR_S " (%s)"),
689 IP_ADDR_V(ncn->vpn_ip), ncn->hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
691 notify_others(ncn, cl, send_add_host);
696 int req_key_h(conn_list_t *cl)
702 if(!cl->status.active)
704 syslog(LOG_ERR, _("Got unauthorized REQ_KEY from " IP_ADDR_S " (%s)"),
705 IP_ADDR_V(cl->vpn_ip), cl->hostname);
709 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
711 syslog(LOG_ERR, _("Got bad REQ_KEY from " IP_ADDR_S " (%s)"),
712 IP_ADDR_V(cl->vpn_ip), cl->hostname);
717 syslog(LOG_DEBUG, _("Got REQ_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
718 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
720 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
721 { /* hey! they want something from ME! :) */
722 send_key_answer(cl, from);
726 fw = lookup_conn(to);
730 syslog(LOG_ERR, _("Attempting to forward REQ_KEY to " IP_ADDR_S ", which does not exist?"),
736 syslog(LOG_DEBUG, _("Forwarding REQ_KEY to " IP_ADDR_S " (%s)"),
737 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
739 cl->buffer[cl->reqlen-1] = '\n';
741 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
743 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
750 void set_keys(conn_list_t *cl, int expiry, char *key)
756 cl->public_key = xmalloc(sizeof(*cl->key));
757 cl->public_key->key = NULL;
760 if(cl->public_key->key)
761 free(cl->public_key->key);
762 cl->public_key->length = strlen(key);
763 cl->public_key->expiry = expiry;
764 cl->public_key->key = xmalloc(cl->public_key->length + 1);
765 strcpy(cl->public_key->key, key);
767 ek = make_shared_key(key);
771 cl->key = xmalloc(sizeof(*cl->key));
778 cl->key->length = strlen(ek);
779 cl->key->expiry = expiry;
780 cl->key->key = xmalloc(cl->key->length + 1);
781 strcpy(cl->key->key, ek);
785 int ans_key_h(conn_list_t *cl)
791 conn_list_t *fw, *gk;
793 if(!cl->status.active)
795 syslog(LOG_ERR, _("Got unauthorized ANS_KEY from " IP_ADDR_S " (%s)"),
796 IP_ADDR_V(cl->vpn_ip), cl->hostname);
800 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
802 syslog(LOG_ERR, _("Got bad ANS_KEY from " IP_ADDR_S " (%s)"),
803 IP_ADDR_V(cl->vpn_ip), cl->hostname);
808 syslog(LOG_DEBUG, _("Got ANS_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
809 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
811 if(to == myself->vpn_ip)
812 { /* hey! that key's for ME! :) */
813 gk = lookup_conn(from);
817 syslog(LOG_ERR, _("Receiving ANS_KEY from " IP_ADDR_S ", which does not exist?"),
822 set_keys(gk, expiry, key);
823 gk->status.validkey = 1;
824 gk->status.waitingforkey = 0;
829 fw = lookup_conn(to);
833 syslog(LOG_ERR, _("Attempting to forward ANS_KEY to " IP_ADDR_S ", which does not exist?"),
839 syslog(LOG_DEBUG, _("Forwarding ANS_KEY to " IP_ADDR_S " (%s)"),
840 IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
842 cl->buffer[cl->reqlen-1] = '\n';
844 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
846 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
853 int key_changed_h(conn_list_t *cl)
858 if(!cl->status.active)
860 syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from " IP_ADDR_S " (%s)"),
861 IP_ADDR_V(cl->vpn_ip), cl->hostname);
865 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
867 syslog(LOG_ERR, _("Got bad KEY_CHANGED from " IP_ADDR_S " (%s)"),
868 IP_ADDR_V(cl->vpn_ip), cl->hostname);
873 syslog(LOG_DEBUG, _("Got KEY_CHANGED origin " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
874 IP_ADDR_V(from), IP_ADDR_V(cl->vpn_ip), cl->hostname);
876 ik = lookup_conn(from);
880 syslog(LOG_ERR, _("Got KEY_CHANGED from " IP_ADDR_S ", which does not exist?"),
885 ik->status.validkey = 0;
886 ik->status.waitingforkey = 0;
888 notify_others(cl, ik, send_key_changed);
893 int (*request_handlers[256])(conn_list_t*) = {
894 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
895 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
896 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
897 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
898 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
899 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
900 add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
908 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
909 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, 0, 0, 0, 0,
913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0