]> git.meshlink.io Git - meshlink/blob - src/net_packet.c
Move listen_sockets to mesh.
[meshlink] / src / net_packet.c
1 /*
2     net_packet.c -- Handles in- and outgoing VPN packets
3     Copyright (C) 2014 Guus Sliepen <guus@meshlink.io>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "system.h"
21
22 #ifdef HAVE_ZLIB
23 #include <zlib.h>
24 #endif
25
26 #include "cipher.h"
27 #include "conf.h"
28 #include "connection.h"
29 #include "crypto.h"
30 #include "digest.h"
31 #include "graph.h"
32 #include "logger.h"
33 #include "meshlink_internal.h"
34 #include "net.h"
35 #include "netutl.h"
36 #include "protocol.h"
37 #include "route.h"
38 #include "utils.h"
39 #include "xalloc.h"
40
41 int keylifetime = 0;
42
43 static void send_udppacket(node_t *, vpn_packet_t *);
44
45 unsigned replaywin = 16;
46
47 #define MAX_SEQNO 1073741824
48
49 /* mtuprobes == 1..30: initial discovery, send bursts with 1 second interval
50    mtuprobes ==    31: sleep pinginterval seconds
51    mtuprobes ==    32: send 1 burst, sleep pingtimeout second
52    mtuprobes ==    33: no response from other side, restart PMTU discovery process
53
54    Probes are sent in batches of at least three, with random sizes between the
55    lower and upper boundaries for the MTU thus far discovered.
56
57    After the initial discovery, a fourth packet is added to each batch with a
58    size larger than the currently known PMTU, to test if the PMTU has increased.
59
60    In case local discovery is enabled, another packet is added to each batch,
61    which will be broadcast to the local network.
62
63 */
64
65 static void send_mtu_probe_handler(void *data) {
66         node_t *n = data;
67         int timeout = 1;
68
69         n->mtuprobes++;
70
71         if(!n->status.reachable || !n->status.validkey) {
72                 logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send MTU probe to unreachable or rekeying node %s (%s)", n->name, n->hostname);
73                 n->mtuprobes = 0;
74                 return;
75         }
76
77         if(n->mtuprobes > 32) {
78                 if(!n->minmtu) {
79                         n->mtuprobes = 31;
80                         timeout = pinginterval;
81                         goto end;
82                 }
83
84                 logger(DEBUG_TRAFFIC, LOG_INFO, "%s (%s) did not respond to UDP ping, restarting PMTU discovery", n->name, n->hostname);
85                 n->status.udp_confirmed = false;
86                 n->mtuprobes = 1;
87                 n->minmtu = 0;
88                 n->maxmtu = MTU;
89         }
90
91         if(n->mtuprobes >= 10 && n->mtuprobes < 32 && !n->minmtu) {
92                 logger(DEBUG_TRAFFIC, LOG_INFO, "No response to MTU probes from %s (%s)", n->name, n->hostname);
93                 n->mtuprobes = 31;
94         }
95
96         if(n->mtuprobes == 30 || (n->mtuprobes < 30 && n->minmtu >= n->maxmtu)) {
97                 if(n->minmtu > n->maxmtu)
98                         n->minmtu = n->maxmtu;
99                 else
100                         n->maxmtu = n->minmtu;
101                 n->mtu = n->minmtu;
102                 logger(DEBUG_TRAFFIC, LOG_INFO, "Fixing MTU of %s (%s) to %d after %d probes", n->name, n->hostname, n->mtu, n->mtuprobes);
103                 n->mtuprobes = 31;
104         }
105
106         if(n->mtuprobes == 31) {
107                 timeout = pinginterval;
108                 goto end;
109         } else if(n->mtuprobes == 32) {
110                 timeout = pingtimeout;
111         }
112
113         for(int i = 0; i < 4 + mesh->localdiscovery; i++) {
114                 int len;
115
116                 if(i == 0) {
117                         if(n->mtuprobes < 30 || n->maxmtu + 8 >= MTU)
118                                 continue;
119                         len = n->maxmtu + 8;
120                 } else if(n->maxmtu <= n->minmtu) {
121                         len = n->maxmtu;
122                 } else {
123                         len = n->minmtu + 1 + rand() % (n->maxmtu - n->minmtu);
124                 }
125
126                 if(len < 64)
127                         len = 64;
128
129                 vpn_packet_t packet;
130                 memset(packet.data, 0, 14);
131                 randomize(packet.data + 14, len - 14);
132                 packet.len = len;
133                 n->status.broadcast = i >= 4 && n->mtuprobes <= 10 && n->prevedge;
134
135                 logger(DEBUG_TRAFFIC, LOG_INFO, "Sending MTU probe length %d to %s (%s)", len, n->name, n->hostname);
136
137                 send_udppacket(n, &packet);
138         }
139
140         n->status.broadcast = false;
141         n->probe_counter = 0;
142         gettimeofday(&n->probe_time, NULL);
143
144         /* Calculate the packet loss of incoming traffic by comparing the rate of
145            packets received to the rate with which the sequence number has increased.
146          */
147
148         if(n->received > n->prev_received)
149                 n->packetloss = 1.0 - (n->received - n->prev_received) / (float)(n->received_seqno - n->prev_received_seqno);
150         else
151                 n->packetloss = n->received_seqno <= n->prev_received_seqno;
152
153         n->prev_received_seqno = n->received_seqno;
154         n->prev_received = n->received;
155
156 end:
157         timeout_set(&n->mtutimeout, &(struct timeval){timeout, rand() % 100000});
158 }
159
160 void send_mtu_probe(node_t *n) {
161         timeout_add(&n->mtutimeout, send_mtu_probe_handler, n, &(struct timeval){1, 0});
162         send_mtu_probe_handler(n);
163 }
164
165 static void mtu_probe_h(node_t *n, vpn_packet_t *packet, uint16_t len) {
166         logger(DEBUG_TRAFFIC, LOG_INFO, "Got MTU probe length %d from %s (%s)", packet->len, n->name, n->hostname);
167
168         if(!packet->data[0]) {
169                 /* It's a probe request, send back a reply */
170
171                 packet->data[0] = 1;
172
173                 /* Temporarily set udp_confirmed, so that the reply is sent
174                    back exactly the way it came in. */
175
176                 bool udp_confirmed = n->status.udp_confirmed;
177                 n->status.udp_confirmed = true;
178                 send_udppacket(n, packet);
179                 n->status.udp_confirmed = udp_confirmed;
180         } else {
181                 /* It's a valid reply: now we know bidirectional communication
182                    is possible using the address and socket that the reply
183                    packet used. */
184
185                 n->status.udp_confirmed = true;
186
187                 /* If we haven't established the PMTU yet, restart the discovery process. */
188
189                 if(n->mtuprobes > 30) {
190                         if (len == n->maxmtu + 8) {
191                                 logger(DEBUG_TRAFFIC, LOG_INFO, "Increase in PMTU to %s (%s) detected, restarting PMTU discovery", n->name, n->hostname);
192                                 n->maxmtu = MTU;
193                                 n->mtuprobes = 10;
194                                 return;
195                         }
196
197                         if(n->minmtu)
198                                 n->mtuprobes = 30;
199                         else
200                                 n->mtuprobes = 1;
201                 }
202
203                 /* If applicable, raise the minimum supported MTU */
204
205                 if(len > n->maxmtu)
206                         len = n->maxmtu;
207                 if(n->minmtu < len)
208                         n->minmtu = len;
209
210                 /* Calculate RTT and bandwidth.
211                    The RTT is the time between the MTU probe burst was sent and the first
212                    reply is received. The bandwidth is measured using the time between the
213                    arrival of the first and third probe reply.
214                  */
215
216                 struct timeval now, diff;
217                 gettimeofday(&now, NULL);
218                 timersub(&now, &n->probe_time, &diff);
219                 
220                 n->probe_counter++;
221
222                 if(n->probe_counter == 1) {
223                         n->rtt = diff.tv_sec + diff.tv_usec * 1e-6;
224                         n->probe_time = now;
225                 } else if(n->probe_counter == 3) {
226                         n->bandwidth = 2.0 * len / (diff.tv_sec + diff.tv_usec * 1e-6);
227                         logger(DEBUG_TRAFFIC, LOG_DEBUG, "%s (%s) RTT %.2f ms, burst bandwidth %.3f Mbit/s, rx packet loss %.2f %%", n->name, n->hostname, n->rtt * 1e3, n->bandwidth * 8e-6, n->packetloss * 1e2);
228                 }
229         }
230 }
231
232 static uint16_t compress_packet(uint8_t *dest, const uint8_t *source, uint16_t len, int level) {
233         if(level == 0) {
234                 memcpy(dest, source, len);
235                 return len;
236         } else if(level == 10) {
237                 return -1;
238         } else if(level < 10) {
239 #ifdef HAVE_ZLIB
240                 unsigned long destlen = MAXSIZE;
241                 if(compress2(dest, &destlen, source, len, level) == Z_OK)
242                         return destlen;
243                 else
244 #endif
245                         return -1;
246         } else {
247                 return -1;
248         }
249
250         return -1;
251 }
252
253 static uint16_t uncompress_packet(uint8_t *dest, const uint8_t *source, uint16_t len, int level) {
254         if(level == 0) {
255                 memcpy(dest, source, len);
256                 return len;
257         } else if(level > 9) {
258                         return -1;
259         }
260 #ifdef HAVE_ZLIB
261         else {
262                 unsigned long destlen = MAXSIZE;
263                 if(uncompress(dest, &destlen, source, len) == Z_OK)
264                         return destlen;
265                 else
266                         return -1;
267         }
268 #endif
269
270         return -1;
271 }
272
273 /* VPN packet I/O */
274
275 static void receive_packet(node_t *n, vpn_packet_t *packet) {
276         logger(DEBUG_TRAFFIC, LOG_DEBUG, "Received packet of %d bytes from %s (%s)",
277                            packet->len, n->name, n->hostname);
278
279         n->in_packets++;
280         n->in_bytes += packet->len;
281
282         route(n, packet);
283 }
284
285 static bool try_mac(node_t *n, const vpn_packet_t *inpkt) {
286         return sptps_verify_datagram(&n->sptps, inpkt->data, inpkt->len);
287 }
288
289 static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
290         if(!n->sptps.state) {
291                 if(!n->status.waitingforkey) {
292                         logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but we haven't exchanged keys yet", n->name, n->hostname);
293                         send_req_key(n);
294                 } else {
295                         logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
296                 }
297                 return;
298         }
299         sptps_receive_data(&n->sptps, inpkt->data, inpkt->len);
300 }
301
302 void receive_tcppacket(connection_t *c, const char *buffer, int len) {
303         vpn_packet_t outpkt;
304
305         if(len > sizeof outpkt.data)
306                 return;
307
308         outpkt.len = len;
309         outpkt.tcp = true;
310         memcpy(outpkt.data, buffer, len);
311
312         receive_packet(c->node, &outpkt);
313 }
314
315 static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
316         if(!n->status.validkey) {
317                 logger(DEBUG_TRAFFIC, LOG_INFO, "No valid key known yet for %s (%s)", n->name, n->hostname);
318                 if(!n->status.waitingforkey)
319                         send_req_key(n);
320                 else if(n->last_req_key + 10 < now.tv_sec) {
321                         logger(DEBUG_ALWAYS, LOG_DEBUG, "No key from %s after 10 seconds, restarting SPTPS", n->name);
322                         sptps_stop(&n->sptps);
323                         n->status.waitingforkey = false;
324                         send_req_key(n);
325                 }
326                 return;
327         }
328
329         uint8_t type = 0;
330
331         // If it's a probe, send it immediately without trying to compress it.
332         if(origpkt->probe) {
333                 sptps_send_record(&n->sptps, PKT_PROBE, origpkt->data, origpkt->len);
334                 return;
335         }
336
337         vpn_packet_t outpkt;
338
339         if(n->outcompression) {
340                 int len = compress_packet(outpkt.data, origpkt->data, origpkt->len, n->outcompression);
341                 if(len < 0) {
342                         logger(DEBUG_TRAFFIC, LOG_ERR, "Error while compressing packet to %s (%s)", n->name, n->hostname);
343                 } else if(len < origpkt->len) {
344                         outpkt.len = len;
345                         origpkt = &outpkt;
346                         type |= PKT_COMPRESSED;
347                 }
348         }
349
350         sptps_send_record(&n->sptps, type, origpkt->data, origpkt->len);
351         return;
352 }
353
354 static void choose_udp_address(const node_t *n, const sockaddr_t **sa, int *sock) {
355         /* Latest guess */
356         *sa = &n->address;
357         *sock = n->sock;
358
359         /* If the UDP address is confirmed, use it. */
360         if(n->status.udp_confirmed)
361                 return;
362
363         /* Send every third packet to n->address; that could be set
364            to the node's reflexive UDP address discovered during key
365            exchange. */
366
367         static int x = 0;
368         if(++x >= 3) {
369                 x = 0;
370                 return;
371         }
372
373         /* Otherwise, address are found in edges to this node.
374            So we pick a random edge and a random socket. */
375
376         int i = 0;
377         int j = rand() % n->edge_tree->count;
378         edge_t *candidate = NULL;
379
380         for splay_each(edge_t, e, n->edge_tree) {
381                 if(i++ == j) {
382                         candidate = e->reverse;
383                         break;
384                 }
385         }
386
387         if(candidate) {
388                 *sa = &candidate->address;
389                 *sock = rand() % mesh->listen_sockets;
390         }
391
392         /* Make sure we have a suitable socket for the chosen address */
393         if(mesh->listen_socket[*sock].sa.sa.sa_family != (*sa)->sa.sa_family) {
394                 for(int i = 0; i < mesh->listen_sockets; i++) {
395                         if(mesh->listen_socket[i].sa.sa.sa_family == (*sa)->sa.sa_family) {
396                                 *sock = i;
397                                 break;
398                         }
399                 }
400         }
401 }
402
403 static void choose_broadcast_address(const node_t *n, const sockaddr_t **sa, int *sock) {
404         static sockaddr_t broadcast_ipv4 = {
405                 .in = {
406                         .sin_family = AF_INET,
407                         .sin_addr.s_addr = -1,
408                 }
409         };
410
411         static sockaddr_t broadcast_ipv6 = {
412                 .in6 = {
413                         .sin6_family = AF_INET6,
414                         .sin6_addr.s6_addr[0x0] = 0xff,
415                         .sin6_addr.s6_addr[0x1] = 0x02,
416                         .sin6_addr.s6_addr[0xf] = 0x01,
417                 }
418         };
419
420         *sock = rand() % mesh->listen_sockets;
421
422         if(mesh->listen_socket[*sock].sa.sa.sa_family == AF_INET6) {
423                 if(mesh->localdiscovery_address.sa.sa_family == AF_INET6) {
424                         mesh->localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port;
425                         *sa = &mesh->localdiscovery_address;
426                 } else {
427                         broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
428                         broadcast_ipv6.in6.sin6_scope_id = mesh->listen_socket[*sock].sa.in6.sin6_scope_id;
429                         *sa = &broadcast_ipv6;
430                 }
431         } else {
432                 if(mesh->localdiscovery_address.sa.sa_family == AF_INET) {
433                         mesh->localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port;
434                         *sa = &mesh->localdiscovery_address;
435                 } else {
436                         broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
437                         *sa = &broadcast_ipv4;
438                 }
439         }
440 }
441
442 static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
443         vpn_packet_t pkt1, pkt2;
444         vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 };
445         vpn_packet_t *inpkt = origpkt;
446         int nextpkt = 0;
447         vpn_packet_t *outpkt;
448         int origlen = origpkt->len;
449         size_t outlen;
450
451         if(!n->status.reachable) {
452                 logger(DEBUG_TRAFFIC, LOG_INFO, "Trying to send UDP packet to unreachable node %s (%s)", n->name, n->hostname);
453                 return;
454         }
455
456         return send_sptps_packet(n, origpkt);
457 }
458
459 bool send_sptps_data(void *handle, uint8_t type, const char *data, size_t len) {
460         node_t *to = handle;
461
462         /* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */
463
464         if(type >= SPTPS_HANDSHAKE || ((mesh->self->options | to->options) & OPTION_TCPONLY) || (type != PKT_PROBE && len > to->minmtu)) {
465                 char buf[len * 4 / 3 + 5];
466                 b64encode(data, buf, len);
467                 /* If no valid key is known yet, send the packets using ANS_KEY requests,
468                    to ensure we get to learn the reflexive UDP address. */
469                 if(!to->status.validkey) {
470                         to->incompression = mesh->self->incompression;
471                         return send_request(to->nexthop->connection, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
472                 } else {
473                         return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
474                 }
475         }
476
477         /* Otherwise, send the packet via UDP */
478
479         const sockaddr_t *sa;
480         int sock;
481
482         if(to->status.broadcast)
483                 choose_broadcast_address(to, &sa, &sock);
484         else
485                 choose_udp_address(to, &sa, &sock);
486
487         if(sendto(mesh->listen_socket[sock].udp.fd, data, len, 0, &sa->sa, SALEN(sa->sa)) < 0 && !sockwouldblock(sockerrno)) {
488                 if(sockmsgsize(sockerrno)) {
489                         if(to->maxmtu >= len)
490                                 to->maxmtu = len - 1;
491                         if(to->mtu >= len)
492                                 to->mtu = len - 1;
493                 } else {
494                         logger(DEBUG_TRAFFIC, LOG_WARNING, "Error sending UDP SPTPS packet to %s (%s): %s", to->name, to->hostname, sockstrerror(sockerrno));
495                         return false;
496                 }
497         }
498
499         return true;
500 }
501
502 bool receive_sptps_record(void *handle, uint8_t type, const char *data, uint16_t len) {
503         node_t *from = handle;
504
505         if(type == SPTPS_HANDSHAKE) {
506                 if(!from->status.validkey) {
507                         from->status.validkey = true;
508                         from->status.waitingforkey = false;
509                         logger(DEBUG_META, LOG_INFO, "SPTPS key exchange with %s (%s) succesful", from->name, from->hostname);
510                 }
511                 return true;
512         }
513
514         if(len > MTU) {
515                 logger(DEBUG_ALWAYS, LOG_ERR, "Packet from %s (%s) larger than maximum supported size (%d > %d)", from->name, from->hostname, len, MTU);
516                 return false;
517         }
518
519         vpn_packet_t inpkt;
520
521         if(type == PKT_PROBE) {
522                 inpkt.len = len;
523                 inpkt.probe = true;
524                 memcpy(inpkt.data, data, len);
525                 mtu_probe_h(from, &inpkt, len);
526                 return true;
527         } else {
528                 inpkt.probe = false;
529         }
530
531         if(type & ~(PKT_COMPRESSED)) {
532                 logger(DEBUG_ALWAYS, LOG_ERR, "Unexpected SPTPS record type %d len %d from %s (%s)", type, len, from->name, from->hostname);
533                 return false;
534         }
535
536         if(type & PKT_COMPRESSED) {
537                 uint16_t ulen = uncompress_packet(inpkt.data, (const uint8_t *)data, len, from->incompression);
538                 if(ulen < 0) {
539                         return false;
540                 } else {
541                         inpkt.len = ulen;
542                 }
543                 if(inpkt.len > MAXSIZE)
544                         abort();
545         } else {
546                 memcpy(inpkt.data, data, len);
547                 inpkt.len = len;
548         }
549
550         receive_packet(from, &inpkt);
551         return true;
552 }
553
554 /*
555   send a packet to the given vpn ip.
556 */
557 void send_packet(node_t *n, vpn_packet_t *packet) {
558         node_t *via;
559
560         if(n == mesh->self) {
561                 n->out_packets++;
562                 n->out_bytes += packet->len;
563                 // TODO: send to application
564                 return;
565         }
566
567         logger(DEBUG_TRAFFIC, LOG_ERR, "Sending packet of %d bytes to %s (%s)",
568                            packet->len, n->name, n->hostname);
569
570         if(!n->status.reachable) {
571                 logger(DEBUG_TRAFFIC, LOG_INFO, "Node %s (%s) is not reachable",
572                                    n->name, n->hostname);
573                 return;
574         }
575
576         n->out_packets++;
577         n->out_bytes += packet->len;
578
579         send_sptps_packet(n, packet);
580         return;
581 }
582
583 /* Broadcast a packet using the minimum spanning tree */
584
585 void broadcast_packet(const node_t *from, vpn_packet_t *packet) {
586         // Always give ourself a copy of the packet.
587         if(from != mesh->self)
588                 send_packet(mesh->self, packet);
589
590         logger(DEBUG_TRAFFIC, LOG_INFO, "Broadcasting packet of %d bytes from %s (%s)",
591                            packet->len, from->name, from->hostname);
592
593         for list_each(connection_t, c, mesh->connections)
594                 if(c->status.active && c->status.mst && c != from->nexthop->connection)
595                         send_packet(c->node, packet);
596 }
597
598 static node_t *try_harder(const sockaddr_t *from, const vpn_packet_t *pkt) {
599         node_t *n = NULL;
600         bool hard = false;
601         static time_t last_hard_try = 0;
602
603         for splay_each(edge_t, e, mesh->edges) {
604                 if(!e->to->status.reachable || e->to == mesh->self)
605                         continue;
606
607                 if(sockaddrcmp_noport(from, &e->address)) {
608                         if(last_hard_try == now.tv_sec)
609                                 continue;
610                         hard = true;
611                 }
612
613                 if(!try_mac(e->to, pkt))
614                         continue;
615
616                 n = e->to;
617                 break;
618         }
619
620         if(hard)
621                 last_hard_try = now.tv_sec;
622
623         last_hard_try = now.tv_sec;
624         return n;
625 }
626
627 void handle_incoming_vpn_data(void *data, int flags) {
628         listen_socket_t *ls = data;
629         vpn_packet_t pkt;
630         char *hostname;
631         sockaddr_t from = {{0}};
632         socklen_t fromlen = sizeof from;
633         node_t *n;
634         int len;
635
636         len = recvfrom(ls->udp.fd, pkt.data, MAXSIZE, 0, &from.sa, &fromlen);
637
638         if(len <= 0 || len > MAXSIZE) {
639                 if(!sockwouldblock(sockerrno))
640                         logger(DEBUG_ALWAYS, LOG_ERR, "Receiving packet failed: %s", sockstrerror(sockerrno));
641                 return;
642         }
643
644         pkt.len = len;
645
646         sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */
647
648         n = lookup_node_udp(&from);
649
650         if(!n) {
651                 n = try_harder(&from, &pkt);
652                 if(n)
653                         update_node_udp(n, &from);
654                 else if(debug_level >= DEBUG_PROTOCOL) {
655                         hostname = sockaddr2hostname(&from);
656                         logger(DEBUG_PROTOCOL, LOG_WARNING, "Received UDP packet from unknown source %s", hostname);
657                         free(hostname);
658                         return;
659                 }
660                 else
661                         return;
662         }
663
664         n->sock = ls - mesh->listen_socket;
665
666         receive_udppacket(n, &pkt);
667 }