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.2 2000/06/25 15:16: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 " (" IP_ADDR_S ")"),
55 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ") activated"),
66 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
71 int send_termreq(conn_list_t *cl)
75 syslog(LOG_DEBUG, _("Sending TERMREQ to " IP_ADDR_S " (" IP_ADDR_S ")"),
76 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
95 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
113 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
131 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
149 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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)
167 real_ip = new_host->real_ip;
168 flags = new_host->flags;
170 /* If we need to propagate information about a new host that wants us to export
171 * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
172 * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
176 if(flags & EXPORTINDIRECTDATA)
178 flags &= ~EXPORTINDIRECTDATA;
179 flags |= INDIRECTDATA;
180 real_ip = myself->vpn_ip;
184 syslog(LOG_DEBUG, _("Sending ADD_HOST for " IP_ADDR_S " (" IP_ADDR_S ") to " IP_ADDR_S " (" IP_ADDR_S ")"),
185 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(real_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
187 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);
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 " IP_ADDR_S " to " IP_ADDR_S " (" IP_ADDR_S ")"),
203 IP_ADDR_V(src->vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " IP_ADDR_S),
231 IP_ADDR_V(cl->real_ip));
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 " IP_ADDR_S " (" IP_ADDR_S ")"),
252 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " IP_ADDR_S " (" IP_ADDR_S ")"),
270 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " IP_ADDR_S ", which does not exist?"),
312 syslog(LOG_DEBUG, _("Sending REQ_KEY to " IP_ADDR_S " (" IP_ADDR_S ")"),
313 IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
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 " IP_ADDR_S ", which does not exist?"),
342 syslog(LOG_DEBUG, _("Sending ANS_KEY to " IP_ADDR_S " (" IP_ADDR_S ")"),
343 IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
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)
396 syslog(LOG_DEBUG, _("Got BASIC_INFO from " IP_ADDR_S), IP_ADDR_V(cl->real_ip));
398 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
400 syslog(LOG_ERR, _("Got bad BASIC_INFO from " IP_ADDR_S),
401 IP_ADDR_V(cl->real_ip));
405 if(cl->protocol_version != PROT_CURRENT)
407 syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
408 cl->protocol_version);
412 if(cl->status.outgoing)
414 if(setup_vpn_connection(cl) < 0)
420 if(setup_vpn_connection(cl) < 0)
428 int passphrase_h(conn_list_t *cl)
431 cl->pp = xmalloc(sizeof(*(cl->pp)));
433 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
435 syslog(LOG_ERR, _("Got bad PASSPHRASE from " IP_ADDR_S " (" IP_ADDR_S ")"),
436 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
439 cl->pp->len = strlen(cl->pp->phrase);
442 syslog(LOG_DEBUG, _("Got PASSPHRASE from " IP_ADDR_S " (" IP_ADDR_S ")"),
443 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
445 if(cl->status.outgoing)
453 int public_key_h(conn_list_t *cl)
458 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
460 syslog(LOG_ERR, _("Got bad PUBLIC_KEY from " IP_ADDR_S " (" IP_ADDR_S ")"),
461 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
466 syslog(LOG_DEBUG, _("Got PUBLIC_KEY from " IP_ADDR_S " (" IP_ADDR_S ")"),
467 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
469 if(verify_passphrase(cl, g_n))
472 syslog(LOG_ERR, _("Intruder: passphrase does not match!"));
476 if(cl->status.outgoing)
482 /* Okay, before we active the connection, we check if there is another entry
483 in the connection list with the same vpn_ip. If so, it presumably is an
484 old connection that has timed out but we don't know it yet. Because our
485 conn_list entry is not active, lookup_conn will skip ourself. */
487 while(old=lookup_conn(cl->vpn_ip))
488 terminate_connection(old);
490 cl->status.active = 1;
491 notify_others(cl, NULL, send_add_host);
498 int ack_h(conn_list_t *cl)
502 syslog(LOG_DEBUG, _("Got ACK from " IP_ADDR_S " (" IP_ADDR_S ")"),
503 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
505 cl->status.active = 1;
506 syslog(LOG_NOTICE, _("Connection with " IP_ADDR_S " (" IP_ADDR_S ") activated"),
507 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
512 int termreq_h(conn_list_t *cl)
516 syslog(LOG_DEBUG, _("Got TERMREQ from " IP_ADDR_S " (" IP_ADDR_S ")"),
517 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
519 cl->status.termreq = 1;
520 terminate_connection(cl);
522 notify_others(cl, NULL, send_del_host);
527 int timeout_h(conn_list_t *cl)
531 syslog(LOG_DEBUG, _("Got TIMEOUT from " IP_ADDR_S " (" IP_ADDR_S ")"),
532 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
534 cl->status.termreq = 1;
535 terminate_connection(cl);
540 int del_host_h(conn_list_t *cl)
545 if(!cl->status.active) return -1;
547 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
549 syslog(LOG_ERR, _("Got bad DEL_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
550 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
555 syslog(LOG_DEBUG, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ")"),
556 IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
558 if(!(fw = lookup_conn(vpn_ip)))
560 syslog(LOG_ERR, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ") which does not exist?"),
561 IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
565 notify_others(cl, fw, send_del_host);
567 fw->status.termreq = 1;
568 terminate_connection(fw);
573 int ping_h(conn_list_t *cl)
577 syslog(LOG_DEBUG, _("Got PING from " IP_ADDR_S " (" IP_ADDR_S ")"),
578 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
580 cl->status.pinged = 0;
581 cl->status.got_pong = 1;
588 int pong_h(conn_list_t *cl)
592 syslog(LOG_DEBUG, _("Got PONG from " IP_ADDR_S " (" IP_ADDR_S ")"),
593 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
595 cl->status.got_pong = 1;
600 int add_host_h(conn_list_t *cl)
607 conn_list_t *ncn, *fw;
609 if(!cl->status.active)
611 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
613 syslog(LOG_ERR, _("Got bad ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
614 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
619 syslog(LOG_DEBUG, _("Got ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
620 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
623 Suggestion of Hans Bayle
625 if((fw = lookup_conn(vpn_ip)))
627 if(fw->nexthop == cl)
628 notify_others(fw, cl, send_add_host);
630 syslog(LOG_DEBUG, _("Invalid ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
631 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
635 ncn = new_conn_list();
636 ncn->real_ip = real_ip;
637 ncn->vpn_ip = vpn_ip;
638 ncn->vpn_mask = vpn_mask;
642 ncn->next = conn_list;
644 ncn->status.active = 1;
645 notify_others(ncn, cl, send_add_host);
650 int req_key_h(conn_list_t *cl)
656 if(!cl->status.active) return -1;
657 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
659 syslog(LOG_ERR, _("Got bad REQ_KEY from " IP_ADDR_S " (" IP_ADDR_S ")"),
660 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
665 syslog(LOG_DEBUG, _("Got REQ_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ")"),
666 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
668 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
669 { /* hey! they want something from ME! :) */
670 send_key_answer(cl, from);
674 fw = lookup_conn(to);
678 syslog(LOG_ERR, _("Attempting to forward REQ_KEY to " IP_ADDR_S ", which does not exist?"),
684 syslog(LOG_DEBUG, _("Forwarding REQ_KEY to " IP_ADDR_S " (" IP_ADDR_S ")"),
685 IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
687 cl->buffer[cl->reqlen-1] = '\n';
689 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
691 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
698 void set_keys(conn_list_t *cl, int expiry, char *key)
704 cl->public_key = xmalloc(sizeof(*cl->key));
705 cl->public_key->key = NULL;
708 if(cl->public_key->key)
709 free(cl->public_key->key);
710 cl->public_key->length = strlen(key);
711 cl->public_key->expiry = expiry;
712 cl->public_key->key = xmalloc(cl->public_key->length + 1);
713 strcpy(cl->public_key->key, key);
715 ek = make_shared_key(key);
719 cl->key = xmalloc(sizeof(*cl->key));
726 cl->key->length = strlen(ek);
727 cl->key->expiry = expiry;
728 cl->key->key = xmalloc(cl->key->length + 1);
729 strcpy(cl->key->key, ek);
733 int ans_key_h(conn_list_t *cl)
739 conn_list_t *fw, *gk;
741 if(!cl->status.active) return -1;
742 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
744 syslog(LOG_ERR, _("Got bad ANS_KEY from " IP_ADDR_S " (" IP_ADDR_S ")"),
745 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
750 syslog(LOG_DEBUG, _("Got ANS_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ")"),
751 IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
753 if(to == myself->vpn_ip)
754 { /* hey! that key's for ME! :) */
755 gk = lookup_conn(from);
759 syslog(LOG_ERR, _("Receiving ANS_KEY from " IP_ADDR_S ", which does not exist?"),
764 set_keys(gk, expiry, key);
765 gk->status.validkey = 1;
766 gk->status.waitingforkey = 0;
771 fw = lookup_conn(to);
775 syslog(LOG_ERR, _("Attempting to forward ANS_KEY to " IP_ADDR_S ", which does not exist?"),
781 syslog(LOG_DEBUG, _("Forwarding ANS_KEY to " IP_ADDR_S " (" IP_ADDR_S ")"),
782 IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
784 cl->buffer[cl->reqlen-1] = '\n';
786 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
788 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
795 int key_changed_h(conn_list_t *cl)
800 if(!cl->status.active) return -1;
801 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
803 syslog(LOG_ERR, _("Got bad KEY_CHANGED from " IP_ADDR_S " (" IP_ADDR_S ")"),
804 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
809 syslog(LOG_DEBUG, _("Got KEY_CHANGED origin " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ")"),
810 IP_ADDR_V(from), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
812 ik = lookup_conn(from);
816 syslog(LOG_ERR, _("Got KEY_CHANGED from " IP_ADDR_S ", which does not exist?"),
821 ik->status.validkey = 0;
822 ik->status.waitingforkey = 0;
824 notify_others(cl, ik, send_key_changed);
829 int (*request_handlers[256])(conn_list_t*) = {
830 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
831 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
833 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
834 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
835 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
836 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
837 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
838 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
839 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
840 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
842 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
844 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
845 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
847 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
848 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0