+ /* Update our copy of the origin's packet key */
+
+ if(from->cipher_pktkey)
+ free(from->cipher_pktkey);
+
+ from->cipher_pktkey = xstrdup(pktkey);
+ keylength /= 2;
+ hex2bin(from->cipher_pktkey, from->cipher_pktkey, keylength);
+ from->cipher_pktkey[keylength] = '\0';
+
+ from->status.validkey = 1;
+ from->status.waitingforkey = 0;
+
+ flush_queue(from);
+cp
+ return 0;
+}
+
+int send_tcppacket(connection_t *cl, vpn_packet_t *packet)
+{
+ int x;
+cp
+ x = send_request(cl->nexthop, "%d %hd", PACKET, packet->len);
+
+ if(x)
+ return x;
+
+ return send_meta(cl->nexthop, packet->data, packet->len);
+}
+
+int tcppacket_h(connection_t *cl)
+{
+ vpn_packet_t packet;
+ char *p;
+ int todo, x;
+cp
+ if(sscanf(cl->buffer, "%*d %hd", &packet.len) != 1)
+ {
+ syslog(LOG_ERR, _("Got bad PACKET from %s (%s)"), cl->name, cl->hostname);
+ return -1;
+ }
+
+ /* Evil hack. */
+
+ p = packet.data;
+ todo = packet.len;
+
+ while(todo)
+ {
+ x = read(cl->meta_socket, p, todo);
+
+ if(x<=0)
+ {
+ if(x==0)
+ syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), cl->name, cl->hostname);
+ else
+ if(errno==EINTR || errno==EAGAIN) /* FIXME: select() or poll() or reimplement this evil hack */
+ continue;
+ else
+ syslog(LOG_ERR, _("Error during reception of PACKET from %s (%s): %m"), cl->name, cl->hostname);
+
+ return -1;
+ }
+
+ todo -= x;
+ p += x;
+ }
+
+ receive_packet(cl, &packet);