1 /*
2
3 silcpacket.c
4
5 Author: Pekka Riikonen <priikone@silcnet.org>
6
7 Copyright (C) 1997 - 2014 Pekka Riikonen
8
9 The contents of this file are subject to one of the Licenses specified
10 in the COPYING file; You may not use this file except in compliance
11 with the License.
12
13 The software distributed under the License is distributed on an "AS IS"
14 basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
15 KIND, either expressed or implied. See the COPYING file for more
16 information.
17
18 */
19 /*
20 * Created: Fri Jul 25 18:52:14 1997
21 */
22 /* $Id$ */
23
24 #include "silc.h"
25
26 /************************** Types and definitions ***************************/
27
28 /* Per scheduler (which usually means per thread) data. We put per scheduler
29 data here for accessing without locking. SILC Schedule dictates that
30 tasks are dispatched in one thread, hence the per scheduler context. */
31 typedef struct {
32 SilcSchedule schedule; /* The scheduler */
33 SilcPacketEngine engine; /* Packet engine */
34 SilcDList inbufs; /* Data inbut buffer list */
35 SilcUInt32 stream_count; /* Number of streams using this */
36 } *SilcPacketEngineContext;
37
38 /* Packet engine */
39 struct SilcPacketEngineStruct {
40 SilcMutex lock; /* Engine lock */
41 SilcRng rng; /* RNG for engine */
42 SilcHashTable contexts; /* Per scheduler contexts */
43 const SilcPacketCallbacks *callbacks; /* Packet callbacks */
44 void *callback_context; /* Context for callbacks */
45 SilcList streams; /* All streams in engine */
46 SilcList packet_pool; /* Free list for received packets */
47 SilcHashTable udp_remote; /* UDP remote streams, or NULL */
48 unsigned int local_is_router : 1;
49 };
50
51 /* Packet processor context */
52 typedef struct SilcPacketProcessStruct {
53 SilcPacketType *types; /* Packets to process */
54 const SilcPacketCallbacks *callbacks; /* Callbacks or NULL */
55 void *callback_context;
56 SilcInt32 priority; /* Priority */
57 } *SilcPacketProcess;
58
59 /* UDP remote stream tuple */
60 typedef struct {
61 char *remote_ip; /* Remote IP address */
62 SilcUInt16 remote_port; /* Remote port */
63 } *SilcPacketRemoteUDP;
64
65 /* Packet stream */
66 struct SilcPacketStreamStruct {
67 struct SilcPacketStreamStruct *next;
68 SilcPacketEngineContext sc; /* Per scheduler context */
69 SilcStream stream; /* Underlaying stream */
70 SilcMutex lock; /* Packet stream lock */
71 SilcDList process; /* Packet processors, or NULL */
72 SilcPacketRemoteUDP remote_udp; /* UDP remote stream tuple, or NULL */
73 void *stream_context; /* Stream context */
74 SilcBufferStruct outbuf; /* Out buffer */
75 SilcBuffer inbuf; /* Inbuf from inbuf list or NULL */
76 SilcCipher send_key[2]; /* Sending key */
77 SilcHmac send_hmac[2]; /* Sending HMAC */
78 SilcCipher receive_key[2]; /* Receiving key */
79 SilcHmac receive_hmac[2]; /* Receiving HMAC */
80 unsigned char *src_id; /* Source ID */
81 unsigned char *dst_id; /* Destination ID */
82 SilcUInt32 send_psn; /* Sending sequence */
83 SilcUInt32 receive_psn; /* Receiving sequence */
84 SilcAtomic32 refcnt; /* Reference counter */
85 SilcUInt8 sid; /* Security ID, set if IV included */
86 unsigned int src_id_len : 6;
87 unsigned int src_id_type : 2;
88 unsigned int dst_id_len : 6;
89 unsigned int dst_id_type : 2;
90 unsigned int is_router : 1; /* Set if router stream */
91 unsigned int destroyed : 1; /* Set if destroyed */
92 unsigned int iv_included : 1; /* Set if IV included */
93 unsigned int udp : 1; /* UDP remote stream */
94 };
95
96 /* Initial size of stream buffers */
97 #define SILC_PACKET_DEFAULT_SIZE 1024
98
99 /* Header length without source and destination ID's. */
100 #define SILC_PACKET_HEADER_LEN 10
101
102 /* Minimum length of SILC Packet Header. */
103 #define SILC_PACKET_MIN_HEADER_LEN 16
104 #define SILC_PACKET_MIN_HEADER_LEN_IV 32 + 1
105
106 /* Maximum padding length */
107 #define SILC_PACKET_MAX_PADLEN 128
108
109 /* Default padding length */
110 #define SILC_PACKET_DEFAULT_PADLEN 16
111
112 /* Minimum packet length */
113 #define SILC_PACKET_MIN_LEN (SILC_PACKET_HEADER_LEN + 1)
114
115 /* Returns true length of the packet. */
116 #define SILC_PACKET_LENGTH(__packetdata, __ret_truelen, __ret_paddedlen) \
117 do { \
118 SILC_GET16_MSB((__ret_truelen), (__packetdata)); \
119 (__ret_paddedlen) = (__ret_truelen) + (SilcUInt8)(__packetdata)[4]; \
120 } while(0)
121
122 /* Calculates the data length with given header length. This macro
123 can be used to check whether the data_len with header_len exceeds
124 SILC_PACKET_MAX_LEN. If it does, this returns the new data_len
125 so that the SILC_PACKET_MAX_LEN is not exceeded. If the data_len
126 plus header_len fits SILC_PACKET_MAX_LEN the returned data length
127 is the data_len given as argument. */
128 #define SILC_PACKET_DATALEN(data_len, header_len) \
129 ((data_len + header_len) > SILC_PACKET_MAX_LEN ? \
130 data_len - ((data_len + header_len) - SILC_PACKET_MAX_LEN) : data_len)
131
132 /* Calculates the length of the padding in the packet. */
133 #define SILC_PACKET_PADLEN(__packetlen, __blocklen, __padlen) \
134 do { \
135 __padlen = (SILC_PACKET_DEFAULT_PADLEN - (__packetlen) % \
136 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
137 if (__padlen < 8) \
138 __padlen += ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN); \
139 } while(0)
140
141 /* Returns the length of the padding up to the maximum length, which
142 is 128 bytes.*/
143 #define SILC_PACKET_PADLEN_MAX(__packetlen, __blocklen, __padlen) \
144 do { \
145 __padlen = (SILC_PACKET_MAX_PADLEN - (__packetlen) % \
146 ((__blocklen) ? (__blocklen) : SILC_PACKET_DEFAULT_PADLEN)); \
147 } while(0)
148
149 /* EOS callback */
150 #define SILC_PACKET_CALLBACK_EOS(s) \
151 do { \
152 (s)->sc->engine->callbacks->eos((s)->sc->engine, s, \
153 (s)->sc->engine->callback_context, \
154 (s)->stream_context); \
155 } while(0)
156
157 /* Error callback */
158 #define SILC_PACKET_CALLBACK_ERROR(s, err) \
159 do { \
160 (s)->sc->engine->callbacks->error((s)->sc->engine, s, err, \
161 (s)->sc->engine->callback_context, \
162 (s)->stream_context); \
163 } while(0)
164
165 static SilcBool silc_packet_dispatch(SilcPacket packet,
166 SilcPacketReceiveCb ignore_handler);
167 static void silc_packet_read_process(SilcPacketStream stream);
168 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
169 SilcPacketType type,
170 SilcPacketFlags flags,
171 SilcIdType src_id_type,
172 unsigned char *src_id,
173 SilcUInt32 src_id_len,
174 SilcIdType dst_id_type,
175 unsigned char *dst_id,
176 SilcUInt32 dst_id_len,
177 const unsigned char *data,
178 SilcUInt32 data_len,
179 SilcCipher cipher,
180 SilcHmac hmac);
181
182 /************************ Static utility functions **************************/
183
184 /* Injects packet to new stream created with silc_packet_stream_add_remote. */
185
SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)186 SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
187 {
188 SilcPacket packet = context;
189 SilcPacketStream stream = packet->stream;
190
191 SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
192
193 silc_mutex_lock(stream->lock);
194 if (!stream->destroyed)
195 silc_packet_dispatch(packet, NULL);
196 silc_mutex_unlock(stream->lock);
197 silc_packet_stream_unref(stream);
198 }
199
200 /* Write data to the stream. Must be called with ps->lock locked. Unlocks
201 the lock inside this function, unless no_unlock is TRUE. Unlocks always
202 in case it returns FALSE. */
203
silc_packet_stream_write(SilcPacketStream ps,SilcBool no_unlock)204 static inline SilcBool silc_packet_stream_write(SilcPacketStream ps,
205 SilcBool no_unlock)
206 {
207 SilcStream stream;
208 SilcBool connected;
209 int i;
210
211 if (ps->udp)
212 stream = ((SilcPacketStream)ps->stream)->stream;
213 else
214 stream = ps->stream;
215
216 if (ps->udp && silc_socket_stream_is_udp(stream, &connected)) {
217 if (!connected) {
218 /* Connectionless UDP stream */
219 while (silc_buffer_len(&ps->outbuf) > 0) {
220 i = silc_net_udp_send(stream, ps->remote_udp->remote_ip,
221 ps->remote_udp->remote_port,
222 ps->outbuf.data, silc_buffer_len(&ps->outbuf));
223 if (silc_unlikely(i == -2)) {
224 /* Error */
225 silc_buffer_reset(&ps->outbuf);
226 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
227 return FALSE;
228 }
229
230 if (silc_unlikely(i == -1)) {
231 /* Cannot write now, write later. */
232 if (!no_unlock)
233 silc_mutex_unlock(ps->lock);
234 return TRUE;
235 }
236
237 /* Wrote data */
238 silc_buffer_pull(&ps->outbuf, i);
239 }
240
241 silc_buffer_reset(&ps->outbuf);
242 if (!no_unlock)
243 silc_mutex_unlock(ps->lock);
244
245 return TRUE;
246 }
247 }
248
249 /* Write the data to the stream */
250 while (silc_buffer_len(&ps->outbuf) > 0) {
251 i = silc_stream_write(stream, ps->outbuf.data,
252 silc_buffer_len(&ps->outbuf));
253 if (silc_unlikely(i == 0)) {
254 /* EOS */
255 silc_buffer_reset(&ps->outbuf);
256 silc_mutex_unlock(ps->lock);
257 SILC_PACKET_CALLBACK_EOS(ps);
258 return FALSE;
259 }
260
261 if (silc_unlikely(i == -2)) {
262 /* Error */
263 silc_buffer_reset(&ps->outbuf);
264 silc_mutex_unlock(ps->lock);
265 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_WRITE);
266 return FALSE;
267 }
268
269 if (silc_unlikely(i == -1)) {
270 /* Cannot write now, write later. */
271 if (!no_unlock)
272 silc_mutex_unlock(ps->lock);
273 return TRUE;
274 }
275
276 /* Wrote data */
277 silc_buffer_pull(&ps->outbuf, i);
278 }
279
280 silc_buffer_reset(&ps->outbuf);
281 if (!no_unlock)
282 silc_mutex_unlock(ps->lock);
283
284 return TRUE;
285 }
286
287 /* Reads data from stream. Must be called with ps->lock locked. If this
288 returns FALSE the lock has been unlocked. If this returns packet stream
289 to `ret_ps' its lock has been acquired and `ps' lock has been unlocked.
290 It is returned if the stream is UDP and remote UDP stream exists for
291 the sender of the packet. */
292
silc_packet_stream_read(SilcPacketStream ps,SilcPacketStream * ret_ps)293 static inline SilcBool silc_packet_stream_read(SilcPacketStream ps,
294 SilcPacketStream *ret_ps)
295 {
296 SilcStream stream = ps->stream;
297 SilcBuffer inbuf;
298 SilcBool connected;
299 int ret;
300
301 /* Get inbuf. If there is already some data for this stream in the buffer
302 we already have it. Otherwise get the current one from list, it will
303 include the data. */
304 inbuf = ps->inbuf;
305 if (!inbuf) {
306 silc_dlist_start(ps->sc->inbufs);
307 inbuf = silc_dlist_get(ps->sc->inbufs);
308 if (!inbuf) {
309 /* Allocate new data input buffer */
310 inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 65);
311 if (!inbuf) {
312 silc_mutex_unlock(ps->lock);
313 return FALSE;
314 }
315 silc_buffer_reset(inbuf);
316 silc_dlist_add(ps->sc->inbufs, inbuf);
317 }
318 }
319
320 /* Make sure there is enough room to read */
321 if (SILC_PACKET_DEFAULT_SIZE * 2 > silc_buffer_taillen(inbuf))
322 silc_buffer_realloc(inbuf, silc_buffer_truelen(inbuf) +
323 (SILC_PACKET_DEFAULT_SIZE * 2));
324
325 if (silc_socket_stream_is_udp(stream, &connected)) {
326 if (!connected) {
327 /* Connectionless UDP stream, read one UDP packet */
328 char remote_ip[64], tuple[64];
329 int remote_port;
330 SilcPacketStream remote;
331
332 ret = silc_net_udp_receive(stream, remote_ip, sizeof(remote_ip),
333 &remote_port, inbuf->tail,
334 silc_buffer_taillen(inbuf));
335
336 if (silc_unlikely(ret < 0)) {
337 silc_mutex_unlock(ps->lock);
338 if (ret == -1) {
339 /* Cannot read now, do it later. */
340 return FALSE;
341 }
342
343 /* Error */
344 silc_buffer_reset(inbuf);
345 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
346 return FALSE;
347 }
348
349 /* See if remote packet stream exist for this sender */
350 silc_snprintf(tuple, sizeof(tuple), "%d%s", remote_port, remote_ip);
351 silc_mutex_lock(ps->sc->engine->lock);
352 if (silc_hash_table_find(ps->sc->engine->udp_remote, tuple, NULL,
353 (void *)&remote)) {
354 silc_mutex_unlock(ps->sc->engine->lock);
355 SILC_LOG_DEBUG(("UDP packet from %s:%d for stream %p", remote_ip,
356 remote_port, remote));
357 silc_mutex_unlock(ps->lock);
358 silc_mutex_lock(remote->lock);
359 *ret_ps = remote;
360 return TRUE;
361 }
362 silc_mutex_unlock(ps->sc->engine->lock);
363
364 /* Unknown sender */
365 if (!ps->remote_udp) {
366 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
367 if (silc_unlikely(!ps->remote_udp)) {
368 silc_mutex_unlock(ps->lock);
369 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_NO_MEMORY);
370 return FALSE;
371 }
372 }
373
374 /* Save sender IP and port */
375 silc_free(ps->remote_udp->remote_ip);
376 ps->remote_udp->remote_ip = strdup(remote_ip);
377 ps->remote_udp->remote_port = remote_port;
378
379 silc_buffer_pull_tail(inbuf, ret);
380 return TRUE;
381 }
382 }
383
384 /* Read data from the stream */
385 ret = silc_stream_read(stream, inbuf->tail, silc_buffer_taillen(inbuf));
386 if (silc_unlikely(ret <= 0)) {
387 silc_mutex_unlock(ps->lock);
388 if (ret == 0) {
389 /* EOS */
390 silc_buffer_reset(inbuf);
391 SILC_PACKET_CALLBACK_EOS(ps);
392 return FALSE;
393 }
394
395 if (ret == -1) {
396 /* Cannot read now, do it later. */
397 return FALSE;
398 }
399
400 /* Error */
401 silc_buffer_reset(inbuf);
402 SILC_PACKET_CALLBACK_ERROR(ps, SILC_PACKET_ERR_READ);
403 return FALSE;
404 }
405
406 silc_buffer_pull_tail(inbuf, ret);
407 return TRUE;
408 }
409
410 /* Our stream IO notifier callback. */
411
silc_packet_stream_io(SilcStream stream,SilcStreamStatus status,void * context)412 static void silc_packet_stream_io(SilcStream stream, SilcStreamStatus status,
413 void *context)
414 {
415 SilcPacketStream remote = NULL, ps = context;
416
417 silc_mutex_lock(ps->lock);
418
419 if (silc_unlikely(ps->destroyed)) {
420 silc_mutex_unlock(ps->lock);
421 return;
422 }
423
424 switch (status) {
425 case SILC_STREAM_CAN_READ:
426 /* Reading is locked also with stream->lock because we may be reading
427 at the same time other thread is writing to same underlaying stream. */
428 SILC_LOG_DEBUG(("Reading data from stream %p, ps %p", ps->stream, ps));
429
430 /* Read data from stream */
431 if (!silc_packet_stream_read(ps, &remote))
432 return;
433
434 /* Now process the data */
435 silc_packet_stream_ref(ps);
436 if (!remote) {
437 silc_packet_read_process(ps);
438 silc_mutex_unlock(ps->lock);
439 } else {
440 silc_packet_read_process(remote);
441 silc_mutex_unlock(remote->lock);
442 }
443 silc_packet_stream_unref(ps);
444 break;
445
446 case SILC_STREAM_CAN_WRITE:
447 SILC_LOG_DEBUG(("Writing pending data to stream %p, ps %p",
448 ps->stream, ps));
449
450 if (silc_unlikely(!silc_buffer_headlen(&ps->outbuf))) {
451 silc_mutex_unlock(ps->lock);
452 return;
453 }
454
455 /* Write pending data to stream */
456 silc_packet_stream_write(ps, FALSE);
457 break;
458
459 default:
460 silc_mutex_unlock(ps->lock);
461 break;
462 }
463 }
464
465 /* Allocate packet */
466
silc_packet_alloc(SilcPacketEngine engine)467 static SilcPacket silc_packet_alloc(SilcPacketEngine engine)
468 {
469 SilcPacket packet;
470
471 SILC_LOG_DEBUG(("Packet pool count %d",
472 silc_list_count(engine->packet_pool)));
473
474 silc_mutex_lock(engine->lock);
475
476 /* Get packet from freelist or allocate new one. */
477 packet = silc_list_get(engine->packet_pool);
478 if (!packet) {
479 void *tmp;
480
481 silc_mutex_unlock(engine->lock);
482
483 packet = silc_calloc(1, sizeof(*packet));
484 if (silc_unlikely(!packet))
485 return NULL;
486
487 SILC_LOG_DEBUG(("Allocating new packet %p", packet));
488
489 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
490 if (silc_unlikely(!tmp)) {
491 silc_free(packet);
492 return NULL;
493 }
494 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
495 silc_buffer_reset(&packet->buffer);
496
497 return packet;
498 }
499
500 SILC_LOG_DEBUG(("Get packet %p", packet));
501
502 /* Delete from freelist */
503 silc_list_del(engine->packet_pool, packet);
504
505 silc_mutex_unlock(engine->lock);
506
507 return packet;
508 }
509
510 /* UDP remote stream hash table destructor */
511
silc_packet_engine_hash_destr(void * key,void * context,void * user_context)512 static void silc_packet_engine_hash_destr(void *key, void *context,
513 void *user_context)
514 {
515 silc_free(key);
516 }
517
518 /* Per scheduler context hash table destructor */
519
silc_packet_engine_context_destr(void * key,void * context,void * user_context)520 static void silc_packet_engine_context_destr(void *key, void *context,
521 void *user_context)
522 {
523 SilcPacketEngineContext sc = context;
524 SilcBuffer buffer;
525
526 silc_dlist_start(sc->inbufs);
527 while ((buffer = silc_dlist_get(sc->inbufs))) {
528 silc_buffer_clear(buffer);
529 silc_buffer_free(buffer);
530 silc_dlist_del(sc->inbufs, buffer);
531 }
532
533 silc_dlist_uninit(sc->inbufs);
534 silc_free(sc);
535 }
536
537
538 /******************************** Packet API ********************************/
539
540 /* Allocate new packet engine */
541
542 SilcPacketEngine
silc_packet_engine_start(SilcRng rng,SilcBool router,const SilcPacketCallbacks * callbacks,void * callback_context)543 silc_packet_engine_start(SilcRng rng, SilcBool router,
544 const SilcPacketCallbacks *callbacks,
545 void *callback_context)
546 {
547 SilcPacketEngine engine;
548 SilcPacket packet;
549 int i;
550 void *tmp;
551
552 SILC_LOG_DEBUG(("Starting new packet engine"));
553
554 if (!callbacks)
555 return NULL;
556 if (!callbacks->packet_receive || !callbacks->eos || !callbacks->error)
557 return NULL;
558
559 engine = silc_calloc(1, sizeof(*engine));
560 if (!engine)
561 return NULL;
562
563 engine->contexts = silc_hash_table_alloc(0, silc_hash_ptr, NULL, NULL, NULL,
564 silc_packet_engine_context_destr,
565 engine, TRUE);
566 if (!engine->contexts) {
567 silc_free(engine);
568 return NULL;
569 }
570
571 engine->rng = rng;
572 engine->local_is_router = router;
573 engine->callbacks = callbacks;
574 engine->callback_context = callback_context;
575 silc_list_init(engine->streams, struct SilcPacketStreamStruct, next);
576 silc_mutex_alloc(&engine->lock);
577
578 /* Allocate packet free list */
579 silc_list_init(engine->packet_pool, struct SilcPacketStruct, next);
580 for (i = 0; i < 5; i++) {
581 packet = silc_calloc(1, sizeof(*packet));
582 if (!packet) {
583 silc_packet_engine_stop(engine);
584 return NULL;
585 }
586
587 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
588 if (!tmp) {
589 silc_packet_engine_stop(engine);
590 return NULL;
591 }
592 silc_buffer_set(&packet->buffer, tmp, SILC_PACKET_DEFAULT_SIZE);
593 silc_buffer_reset(&packet->buffer);
594
595 silc_list_add(engine->packet_pool, packet);
596 }
597 silc_list_start(engine->packet_pool);
598
599 return engine;
600 }
601
602 /* Stop packet engine */
603
silc_packet_engine_stop(SilcPacketEngine engine)604 void silc_packet_engine_stop(SilcPacketEngine engine)
605 {
606 SilcPacket packet;
607
608 SILC_LOG_DEBUG(("Stopping packet engine"));
609
610 if (!engine)
611 return;
612
613 /* Free packet free list */
614 silc_list_start(engine->packet_pool);
615 while ((packet = silc_list_get(engine->packet_pool))) {
616 silc_buffer_purge(&packet->buffer);
617 silc_free(packet);
618 }
619
620 silc_hash_table_free(engine->contexts);
621 silc_mutex_free(engine->lock);
622 silc_free(engine);
623 }
624
625 static const char * const packet_error[] = {
626 "Cannot read from stream",
627 "Cannot write to stream",
628 "Packet MAC failed",
629 "Packet decryption failed",
630 "Unknown SID",
631 "Packet is malformed",
632 "System out of memory",
633 };
634
635 /* Return packet error string */
636
silc_packet_error_string(SilcPacketError error)637 const char *silc_packet_error_string(SilcPacketError error)
638 {
639 if (error < SILC_PACKET_ERR_READ || error > SILC_PACKET_ERR_NO_MEMORY)
640 return "<invalid error code>";
641 return packet_error[error];
642 }
643
644 /* Return list of packet streams in the engine */
645
silc_packet_engine_get_streams(SilcPacketEngine engine)646 SilcDList silc_packet_engine_get_streams(SilcPacketEngine engine)
647 {
648 SilcDList list;
649 SilcPacketStream ps;
650
651 list = silc_dlist_init();
652 if (!list)
653 return NULL;
654
655 silc_mutex_lock(engine->lock);
656 silc_list_start(engine->streams);
657 while ((ps = silc_list_get(engine->streams))) {
658 silc_packet_stream_ref(ps);
659 silc_dlist_add(list, ps);
660 }
661 silc_mutex_unlock(engine->lock);
662
663 return list;
664 }
665
666 /* Free list returned by silc_packet_engine_get_streams */
667
silc_packet_engine_free_streams_list(SilcDList streams)668 void silc_packet_engine_free_streams_list(SilcDList streams)
669 {
670 SilcPacketStream ps;
671
672 silc_dlist_start(streams);
673 while ((ps = silc_dlist_get(streams)))
674 silc_packet_stream_unref(ps);
675
676 silc_dlist_uninit(streams);
677 }
678
679 /* Create new packet stream */
680
silc_packet_stream_create(SilcPacketEngine engine,SilcSchedule schedule,SilcStream stream)681 SilcPacketStream silc_packet_stream_create(SilcPacketEngine engine,
682 SilcSchedule schedule,
683 SilcStream stream)
684 {
685 SilcPacketStream ps;
686 SilcBuffer inbuf;
687 void *tmp;
688
689 SILC_LOG_DEBUG(("Creating new packet stream"));
690
691 if (!engine || !stream)
692 return NULL;
693
694 ps = silc_calloc(1, sizeof(*ps));
695 if (!ps)
696 return NULL;
697
698 ps->stream = stream;
699 silc_atomic_init32(&ps->refcnt, 1);
700 silc_mutex_alloc(&ps->lock);
701
702 /* Allocate out buffer */
703 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
704 if (!tmp) {
705 silc_packet_stream_destroy(ps);
706 return NULL;
707 }
708 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
709 silc_buffer_reset(&ps->outbuf);
710
711 /* Initialize packet procesors list */
712 ps->process = silc_dlist_init();
713 if (!ps->process) {
714 ps->stream = NULL;
715 silc_packet_stream_destroy(ps);
716 return NULL;
717 }
718
719 silc_mutex_lock(engine->lock);
720
721 /* Add per scheduler context */
722 if (!silc_hash_table_find(engine->contexts, schedule, NULL,
723 (void *)&ps->sc)) {
724 ps->sc = silc_calloc(1, sizeof(*ps->sc));
725 if (!ps->sc) {
726 silc_mutex_unlock(engine->lock);
727 ps->stream = NULL;
728 silc_packet_stream_destroy(ps);
729 return NULL;
730 }
731 ps->sc->engine = engine;
732 ps->sc->schedule = schedule;
733
734 /* Allocate data input buffer */
735 inbuf = silc_buffer_alloc(SILC_PACKET_DEFAULT_SIZE * 65);
736 if (!inbuf) {
737 silc_free(ps->sc);
738 ps->sc = NULL;
739 silc_mutex_unlock(engine->lock);
740 ps->stream = NULL;
741 silc_packet_stream_destroy(ps);
742 return NULL;
743 }
744 silc_buffer_reset(inbuf);
745
746 ps->sc->inbufs = silc_dlist_init();
747 if (!ps->sc->inbufs) {
748 silc_buffer_free(inbuf);
749 silc_free(ps->sc);
750 ps->sc = NULL;
751 silc_mutex_unlock(engine->lock);
752 ps->stream = NULL;
753 silc_packet_stream_destroy(ps);
754 return NULL;
755 }
756 silc_dlist_add(ps->sc->inbufs, inbuf);
757
758 /* Add to per scheduler context hash table */
759 if (!silc_hash_table_add(engine->contexts, schedule, ps->sc)) {
760 silc_buffer_free(inbuf);
761 silc_dlist_del(ps->sc->inbufs, inbuf);
762 silc_free(ps->sc);
763 ps->sc = NULL;
764 silc_mutex_unlock(engine->lock);
765 ps->stream = NULL;
766 silc_packet_stream_destroy(ps);
767 return NULL;
768 }
769 }
770 ps->sc->stream_count++;
771
772 /* Add the packet stream to engine */
773 silc_list_add(engine->streams, ps);
774
775 /* If this is UDP stream, allocate UDP remote stream hash table */
776 if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
777 engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
778 silc_hash_string_compare, NULL,
779 silc_packet_engine_hash_destr,
780 NULL, TRUE);
781
782 silc_mutex_unlock(engine->lock);
783
784 /* Set IO notifier callback. This schedules this stream for I/O. */
785 if (!silc_stream_set_notifier(ps->stream, schedule,
786 silc_packet_stream_io, ps)) {
787 SILC_LOG_DEBUG(("Cannot set stream notifier for packet stream"));
788 ps->stream = NULL;
789 silc_packet_stream_destroy(ps);
790 return NULL;
791 }
792
793 SILC_LOG_DEBUG(("Created packet stream %p", ps));
794
795 return ps;
796 }
797
798 /* Add new remote packet stream for UDP packet streams */
799
silc_packet_stream_add_remote(SilcPacketStream stream,const char * remote_ip,SilcUInt16 remote_port,SilcPacket packet)800 SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
801 const char *remote_ip,
802 SilcUInt16 remote_port,
803 SilcPacket packet)
804 {
805 SilcPacketEngine engine = stream->sc->engine;
806 SilcPacketStream ps;
807 char *tuple;
808 void *tmp;
809
810 SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
811 remote_ip, remote_port, stream));
812
813 if (!stream || !remote_ip || !remote_port)
814 return NULL;
815
816 if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
817 SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
818 return NULL;
819 }
820
821 ps = silc_calloc(1, sizeof(*ps));
822 if (!ps)
823 return NULL;
824 ps->sc = stream->sc;
825
826 silc_atomic_init32(&ps->refcnt, 1);
827 silc_mutex_alloc(&ps->lock);
828
829 /* Set the UDP packet stream as underlaying stream */
830 silc_packet_stream_ref(stream);
831 ps->stream = (SilcStream)stream;
832 ps->udp = TRUE;
833
834 /* Allocate out buffer */
835 tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
836 if (!tmp) {
837 silc_packet_stream_destroy(ps);
838 return NULL;
839 }
840 silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
841 silc_buffer_reset(&ps->outbuf);
842
843 /* Initialize packet procesors list */
844 ps->process = silc_dlist_init();
845 if (!ps->process) {
846 silc_packet_stream_destroy(ps);
847 return NULL;
848 }
849
850 /* Add to engine with this IP and port pair */
851 tuple = silc_format("%d%s", remote_port, remote_ip);
852 silc_mutex_lock(engine->lock);
853 if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
854 silc_mutex_unlock(engine->lock);
855 silc_packet_stream_destroy(ps);
856 return NULL;
857 }
858 silc_mutex_unlock(engine->lock);
859
860 /* Save remote IP and port pair */
861 ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
862 if (!ps->remote_udp) {
863 silc_packet_stream_destroy(ps);
864 return NULL;
865 }
866 ps->remote_udp->remote_port = remote_port;
867 ps->remote_udp->remote_ip = strdup(remote_ip);
868 if (!ps->remote_udp->remote_ip) {
869 silc_packet_stream_destroy(ps);
870 return NULL;
871 }
872
873 if (packet) {
874 /* Inject packet to the new stream */
875 silc_packet_stream_inject(ps, packet);
876 }
877
878 return ps;
879 }
880
881 /* Inject packet to packet stream */
882
silc_packet_stream_inject(SilcPacketStream stream,SilcPacket packet)883 SilcBool silc_packet_stream_inject(SilcPacketStream stream,
884 SilcPacket packet)
885 {
886 packet->stream = stream;
887 silc_packet_stream_ref(stream);
888 return !!silc_schedule_task_add_timeout(
889 silc_stream_get_schedule(stream->stream),
890 silc_packet_stream_inject_packet, packet,
891 0, 0);
892 }
893
894 /* Destroy packet stream */
895
silc_packet_stream_destroy(SilcPacketStream stream)896 void silc_packet_stream_destroy(SilcPacketStream stream)
897 {
898 SilcPacketEngine engine;
899
900 if (!stream)
901 return;
902
903 if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0) {
904 if (stream->destroyed)
905 return;
906 stream->destroyed = TRUE;
907
908 SILC_LOG_DEBUG(("Marking packet stream %p destroyed", stream));
909
910 /* Close the underlaying stream */
911 if (!stream->udp && stream->stream)
912 silc_stream_close(stream->stream);
913 return;
914 }
915
916 SILC_LOG_DEBUG(("Destroying packet stream %p", stream));
917
918 if (!stream->udp) {
919 /* Delete from engine */
920 if (stream->sc) {
921 engine = stream->sc->engine;
922 silc_mutex_lock(engine->lock);
923 silc_list_del(engine->streams, stream);
924
925 /* Remove per scheduler context, if it is not used anymore */
926 stream->sc->stream_count--;
927 if (!stream->sc->stream_count)
928 silc_hash_table_del(engine->contexts, stream->sc->schedule);
929
930 silc_mutex_unlock(engine->lock);
931 }
932
933 /* Destroy the underlaying stream */
934 if (stream->stream)
935 silc_stream_destroy(stream->stream);
936 } else {
937 /* Delete from UDP remote hash table */
938 char tuple[64];
939 engine = stream->sc->engine;
940 silc_snprintf(tuple, sizeof(tuple), "%d%s",
941 stream->remote_udp->remote_port,
942 stream->remote_udp->remote_ip);
943 silc_mutex_lock(engine->lock);
944 silc_hash_table_del(engine->udp_remote, tuple);
945 silc_mutex_unlock(engine->lock);
946
947 silc_free(stream->remote_udp->remote_ip);
948 silc_free(stream->remote_udp);
949
950 /* Unreference the underlaying packet stream */
951 silc_packet_stream_unref((SilcPacketStream)stream->stream);
952 }
953
954 /* Clear and free buffers */
955 silc_buffer_clear(&stream->outbuf);
956 silc_buffer_purge(&stream->outbuf);
957
958 if (stream->process) {
959 SilcPacketProcess p;
960 silc_dlist_start(stream->process);
961 while ((p = silc_dlist_get(stream->process))) {
962 silc_free(p->types);
963 silc_free(p);
964 silc_dlist_del(stream->process, p);
965 }
966 silc_dlist_uninit(stream->process);
967 }
968
969 /* Destroy ciphers and HMACs */
970 if (stream->send_key[0])
971 silc_cipher_free(stream->send_key[0]);
972 if (stream->receive_key[0])
973 silc_cipher_free(stream->receive_key[0]);
974 if (stream->send_hmac[0])
975 silc_hmac_free(stream->send_hmac[0]);
976 if (stream->receive_hmac[0])
977 silc_hmac_free(stream->receive_hmac[0]);
978 if (stream->send_key[1])
979 silc_cipher_free(stream->send_key[1]);
980 if (stream->receive_key[1])
981 silc_cipher_free(stream->receive_key[1]);
982 if (stream->send_hmac[1])
983 silc_hmac_free(stream->send_hmac[1]);
984 if (stream->receive_hmac[1])
985 silc_hmac_free(stream->receive_hmac[1]);
986
987 /* Free IDs */
988 silc_free(stream->src_id);
989 silc_free(stream->dst_id);
990
991 silc_atomic_uninit32(&stream->refcnt);
992 silc_mutex_free(stream->lock);
993 silc_free(stream);
994 }
995
996 /* Return TRUE if the stream is valid */
997
silc_packet_stream_is_valid(SilcPacketStream stream)998 SilcBool silc_packet_stream_is_valid(SilcPacketStream stream)
999 {
1000 return stream->destroyed == FALSE;
1001 }
1002
1003 /* Marks as router stream */
1004
silc_packet_stream_set_router(SilcPacketStream stream)1005 void silc_packet_stream_set_router(SilcPacketStream stream)
1006 {
1007 stream->is_router = TRUE;
1008 }
1009
1010 /* Mark to include IV in ciphertext */
1011
silc_packet_stream_set_iv_included(SilcPacketStream stream)1012 void silc_packet_stream_set_iv_included(SilcPacketStream stream)
1013 {
1014 stream->iv_included = TRUE;
1015 }
1016
1017 /* Links `callbacks' to `stream' for specified packet types */
1018
silc_packet_stream_link_va(SilcPacketStream stream,const SilcPacketCallbacks * callbacks,void * callback_context,int priority,va_list ap)1019 static SilcBool silc_packet_stream_link_va(SilcPacketStream stream,
1020 const SilcPacketCallbacks *callbacks,
1021 void *callback_context,
1022 int priority, va_list ap)
1023 {
1024 SilcPacketProcess p, e;
1025 SilcInt32 packet_type;
1026 int i;
1027
1028 SILC_LOG_DEBUG(("Linking callbacks %p to stream %p", callbacks, stream));
1029
1030 if (!callbacks)
1031 return FALSE;
1032 if (!callbacks->packet_receive)
1033 return FALSE;
1034
1035 p = silc_calloc(1, sizeof(*p));
1036 if (!p)
1037 return FALSE;
1038
1039 p->priority = priority;
1040 p->callbacks = callbacks;
1041 p->callback_context = callback_context;
1042
1043 silc_mutex_lock(stream->lock);
1044
1045 if (!stream->process) {
1046 stream->process = silc_dlist_init();
1047 if (!stream->process) {
1048 silc_mutex_unlock(stream->lock);
1049 silc_free(p);
1050 return FALSE;
1051 }
1052 }
1053
1054 /* According to priority set the procesor to correct position. First
1055 entry has the highest priority */
1056 silc_dlist_start(stream->process);
1057 while ((e = silc_dlist_get(stream->process)) != SILC_LIST_END) {
1058 if (p->priority > e->priority) {
1059 silc_dlist_insert(stream->process, p);
1060 break;
1061 }
1062 }
1063 if (!e)
1064 silc_dlist_add(stream->process, p);
1065
1066 /* Get packet types to process */
1067 i = 1;
1068 while (1) {
1069 packet_type = va_arg(ap, SilcInt32);
1070
1071 if (packet_type == SILC_PACKET_ANY)
1072 break;
1073
1074 if (packet_type == -1)
1075 break;
1076
1077 p->types = silc_realloc(p->types, sizeof(*p->types) * (i + 1));
1078 if (!p->types) {
1079 silc_mutex_unlock(stream->lock);
1080 return FALSE;
1081 }
1082
1083 p->types[i - 1] = (SilcPacketType)packet_type;
1084 i++;
1085 }
1086 if (p->types)
1087 p->types[i - 1] = 0;
1088
1089 silc_mutex_unlock(stream->lock);
1090
1091 silc_packet_stream_ref(stream);
1092
1093 return TRUE;
1094 }
1095
1096 /* Links `callbacks' to `stream' for specified packet types */
1097
silc_packet_stream_link(SilcPacketStream stream,const SilcPacketCallbacks * callbacks,void * callback_context,int priority,...)1098 SilcBool silc_packet_stream_link(SilcPacketStream stream,
1099 const SilcPacketCallbacks *callbacks,
1100 void *callback_context,
1101 int priority, ...)
1102 {
1103 va_list ap;
1104 SilcBool ret;
1105
1106 va_start(ap, priority);
1107 ret = silc_packet_stream_link_va(stream, callbacks, callback_context,
1108 priority, ap);
1109 va_end(ap);
1110
1111 return ret;
1112 }
1113
1114 /* Unlinks `callbacks' from `stream'. */
1115
silc_packet_stream_unlink(SilcPacketStream stream,const SilcPacketCallbacks * callbacks,void * callback_context)1116 void silc_packet_stream_unlink(SilcPacketStream stream,
1117 const SilcPacketCallbacks *callbacks,
1118 void *callback_context)
1119 {
1120 SilcPacketProcess p;
1121
1122 SILC_LOG_DEBUG(("Unlinking callbacks %p from stream %p",
1123 callbacks, stream));
1124
1125 silc_mutex_lock(stream->lock);
1126
1127 silc_dlist_start(stream->process);
1128 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END)
1129 if (p->callbacks == callbacks &&
1130 p->callback_context == callback_context) {
1131 silc_dlist_del(stream->process, p);
1132 silc_free(p->types);
1133 silc_free(p);
1134 break;
1135 }
1136
1137 if (!silc_dlist_count(stream->process)) {
1138 silc_dlist_uninit(stream->process);
1139 stream->process = NULL;
1140 }
1141
1142 silc_mutex_unlock(stream->lock);
1143
1144 silc_packet_stream_unref(stream);
1145 }
1146
1147 /* Returns TRUE if stream is UDP stream */
1148
silc_packet_stream_is_udp(SilcPacketStream stream)1149 SilcBool silc_packet_stream_is_udp(SilcPacketStream stream)
1150 {
1151 return stream->udp || silc_socket_stream_is_udp(stream->stream, NULL);
1152 }
1153
1154 /* Return packet sender IP and port for UDP packet stream */
1155
silc_packet_get_sender(SilcPacket packet,const char ** sender_ip,SilcUInt16 * sender_port)1156 SilcBool silc_packet_get_sender(SilcPacket packet,
1157 const char **sender_ip,
1158 SilcUInt16 *sender_port)
1159 {
1160 if (!packet->stream->remote_udp)
1161 return FALSE;
1162
1163 *sender_ip = packet->stream->remote_udp->remote_ip;
1164 *sender_port = packet->stream->remote_udp->remote_port;
1165
1166 return TRUE;
1167 }
1168
1169 /* Reference packet stream */
1170
silc_packet_stream_ref(SilcPacketStream stream)1171 void silc_packet_stream_ref(SilcPacketStream stream)
1172 {
1173 silc_atomic_add_int32(&stream->refcnt, 1);
1174 SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1175 silc_atomic_get_int32(&stream->refcnt) - 1,
1176 silc_atomic_get_int32(&stream->refcnt)));
1177 }
1178
1179 /* Unreference packet stream */
1180
silc_packet_stream_unref(SilcPacketStream stream)1181 void silc_packet_stream_unref(SilcPacketStream stream)
1182 {
1183 SILC_LOG_DEBUG(("Stream %p, refcnt %d->%d", stream,
1184 silc_atomic_get_int32(&stream->refcnt),
1185 silc_atomic_get_int32(&stream->refcnt) - 1));
1186 if (silc_atomic_sub_int32(&stream->refcnt, 1) > 0)
1187 return;
1188 silc_atomic_add_int32(&stream->refcnt, 1);
1189 silc_packet_stream_destroy(stream);
1190 }
1191
1192 /* Return engine */
1193
silc_packet_get_engine(SilcPacketStream stream)1194 SilcPacketEngine silc_packet_get_engine(SilcPacketStream stream)
1195 {
1196 return stream->sc->engine;
1197 }
1198
1199 /* Set application context for packet stream */
1200
silc_packet_set_context(SilcPacketStream stream,void * stream_context)1201 void silc_packet_set_context(SilcPacketStream stream, void *stream_context)
1202 {
1203 silc_mutex_lock(stream->lock);
1204 stream->stream_context = stream_context;
1205 silc_mutex_unlock(stream->lock);
1206 }
1207
1208 /* Return application context from packet stream */
1209
silc_packet_get_context(SilcPacketStream stream)1210 void *silc_packet_get_context(SilcPacketStream stream)
1211 {
1212 void *context;
1213 silc_mutex_lock(stream->lock);
1214 context = stream->stream_context;
1215 silc_mutex_unlock(stream->lock);
1216 return context;
1217 }
1218
1219 /* Change underlaying stream */
1220
silc_packet_stream_set_stream(SilcPacketStream ps,SilcStream stream)1221 void silc_packet_stream_set_stream(SilcPacketStream ps,
1222 SilcStream stream)
1223 {
1224 if (ps->stream)
1225 silc_stream_set_notifier(ps->stream, ps->sc->schedule, NULL, NULL);
1226 ps->stream = stream;
1227 silc_stream_set_notifier(ps->stream, ps->sc->schedule, silc_packet_stream_io,
1228 ps);
1229 }
1230
1231 /* Return underlaying stream */
1232
silc_packet_stream_get_stream(SilcPacketStream stream)1233 SilcStream silc_packet_stream_get_stream(SilcPacketStream stream)
1234 {
1235 return stream->stream;
1236 }
1237
1238 /* Set keys. */
1239
silc_packet_set_keys(SilcPacketStream stream,SilcCipher send_key,SilcCipher receive_key,SilcHmac send_hmac,SilcHmac receive_hmac,SilcBool rekey)1240 SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key,
1241 SilcCipher receive_key, SilcHmac send_hmac,
1242 SilcHmac receive_hmac, SilcBool rekey)
1243 {
1244 SILC_LOG_DEBUG(("Setting new keys to packet stream %p", stream));
1245
1246 /* If doing rekey, send REKEY_DONE packet */
1247 if (rekey) {
1248 /* This will take stream lock. */
1249 if (!silc_packet_send_raw(stream, SILC_PACKET_REKEY_DONE, 0,
1250 stream->src_id_type, stream->src_id,
1251 stream->src_id_len, stream->dst_id_type,
1252 stream->dst_id, stream->dst_id_len,
1253 NULL, 0, stream->send_key[0],
1254 stream->send_hmac[0]))
1255 return FALSE;
1256
1257 /* Write the packet to the stream */
1258 if (!silc_packet_stream_write(stream, TRUE))
1259 return FALSE;
1260 } else {
1261 silc_mutex_lock(stream->lock);
1262 }
1263
1264 /* In case IV Included is set, save the old keys */
1265 if (stream->iv_included) {
1266 if (stream->send_key[1] && send_key) {
1267 silc_cipher_free(stream->send_key[1]);
1268 stream->send_key[1] = stream->send_key[0];
1269 }
1270 if (stream->receive_key[1] && receive_key) {
1271 silc_cipher_free(stream->receive_key[1]);
1272 stream->receive_key[1] = stream->receive_key[0];
1273 }
1274 if (stream->send_hmac[1] && send_hmac) {
1275 silc_hmac_free(stream->send_hmac[1]);
1276 stream->send_hmac[1] = stream->send_hmac[0];
1277 }
1278 if (stream->receive_hmac[1] && receive_hmac) {
1279 silc_hmac_free(stream->receive_hmac[1]);
1280 stream->receive_hmac[1] = stream->receive_hmac[0];
1281 }
1282 } else {
1283 if (stream->send_key[0] && send_key)
1284 silc_cipher_free(stream->send_key[0]);
1285 if (stream->receive_key[0] && receive_key)
1286 silc_cipher_free(stream->receive_key[0]);
1287 if (stream->send_hmac[0] && send_hmac)
1288 silc_hmac_free(stream->send_hmac[0]);
1289 if (stream->receive_hmac[0] && receive_hmac)
1290 silc_hmac_free(stream->receive_hmac[0]);
1291 }
1292
1293 /* Set keys */
1294 if (send_key)
1295 stream->send_key[0] = send_key;
1296 if (receive_key)
1297 stream->receive_key[0] = receive_key;
1298 if (send_hmac)
1299 stream->send_hmac[0] = send_hmac;
1300 if (receive_hmac)
1301 stream->receive_hmac[0] = receive_hmac;
1302
1303 silc_mutex_unlock(stream->lock);
1304 return TRUE;
1305 }
1306
1307 /* Return current ciphers from packet stream */
1308
silc_packet_get_keys(SilcPacketStream stream,SilcCipher * send_key,SilcCipher * receive_key,SilcHmac * send_hmac,SilcHmac * receive_hmac)1309 SilcBool silc_packet_get_keys(SilcPacketStream stream,
1310 SilcCipher *send_key,
1311 SilcCipher *receive_key,
1312 SilcHmac *send_hmac,
1313 SilcHmac *receive_hmac)
1314 {
1315 if (!stream->send_key[0] && !stream->receive_key[0] &&
1316 !stream->send_hmac[0] && !stream->receive_hmac[0])
1317 return FALSE;
1318
1319 silc_mutex_lock(stream->lock);
1320
1321 if (send_key)
1322 *send_key = stream->send_key[0];
1323 if (receive_key)
1324 *receive_key = stream->receive_key[0];
1325 if (send_hmac)
1326 *send_hmac = stream->send_hmac[0];
1327 if (receive_hmac)
1328 *receive_hmac = stream->receive_hmac[0];
1329
1330 silc_mutex_unlock(stream->lock);
1331
1332 return TRUE;
1333 }
1334
1335 /* Set SILC IDs to packet stream */
1336
silc_packet_set_ids(SilcPacketStream stream,SilcIdType src_id_type,const void * src_id,SilcIdType dst_id_type,const void * dst_id)1337 SilcBool silc_packet_set_ids(SilcPacketStream stream,
1338 SilcIdType src_id_type, const void *src_id,
1339 SilcIdType dst_id_type, const void *dst_id)
1340 {
1341 SilcUInt32 len;
1342 unsigned char tmp[32];
1343 void *tmp_id;
1344
1345 if (!src_id && !dst_id)
1346 return FALSE;
1347
1348 silc_mutex_lock(stream->lock);
1349
1350 if (src_id) {
1351 SILC_LOG_DEBUG(("Setting source ID to packet stream %p", stream));
1352
1353 if (!silc_id_id2str(src_id, src_id_type, tmp, sizeof(tmp), &len)) {
1354 silc_mutex_unlock(stream->lock);
1355 return FALSE;
1356 }
1357 tmp_id = silc_memdup(tmp, len);
1358 if (!tmp_id) {
1359 silc_mutex_unlock(stream->lock);
1360 return FALSE;
1361 }
1362 silc_free(stream->src_id);
1363 stream->src_id = tmp_id;
1364 stream->src_id_type = src_id_type;
1365 stream->src_id_len = len;
1366 }
1367
1368 if (dst_id) {
1369 SILC_LOG_DEBUG(("Setting destination ID to packet stream %p", stream));
1370
1371 if (!silc_id_id2str(dst_id, dst_id_type, tmp, sizeof(tmp), &len)) {
1372 silc_mutex_unlock(stream->lock);
1373 return FALSE;
1374 }
1375 tmp_id = silc_memdup(tmp, len);
1376 if (!tmp_id) {
1377 silc_mutex_unlock(stream->lock);
1378 return FALSE;
1379 }
1380 silc_free(stream->dst_id);
1381 stream->dst_id = tmp_id;
1382 stream->dst_id_type = dst_id_type;
1383 stream->dst_id_len = len;
1384 }
1385
1386 silc_mutex_unlock(stream->lock);
1387
1388 return TRUE;
1389 }
1390
1391 /* Return IDs from the packet stream */
1392
silc_packet_get_ids(SilcPacketStream stream,SilcBool * src_id_set,SilcID * src_id,SilcBool * dst_id_set,SilcID * dst_id)1393 SilcBool silc_packet_get_ids(SilcPacketStream stream,
1394 SilcBool *src_id_set, SilcID *src_id,
1395 SilcBool *dst_id_set, SilcID *dst_id)
1396 {
1397 if (src_id && stream->src_id)
1398 if (!silc_id_str2id2(stream->src_id, stream->src_id_len,
1399 stream->src_id_type, src_id))
1400 return FALSE;
1401
1402 if (stream->src_id && src_id_set)
1403 *src_id_set = TRUE;
1404
1405 if (dst_id && stream->dst_id)
1406 if (!silc_id_str2id2(stream->dst_id, stream->dst_id_len,
1407 stream->dst_id_type, dst_id))
1408 return FALSE;
1409
1410 if (stream->dst_id && dst_id_set)
1411 *dst_id_set = TRUE;
1412
1413 return TRUE;
1414 }
1415
1416 /* Adds Security ID (SID) */
1417
silc_packet_set_sid(SilcPacketStream stream,SilcUInt8 sid)1418 SilcBool silc_packet_set_sid(SilcPacketStream stream, SilcUInt8 sid)
1419 {
1420 if (!stream->iv_included)
1421 return FALSE;
1422
1423 SILC_LOG_DEBUG(("Set packet stream %p SID to %d", stream, sid));
1424
1425 stream->sid = sid;
1426 return TRUE;
1427 }
1428
1429 /* Free packet */
1430
silc_packet_free(SilcPacket packet)1431 void silc_packet_free(SilcPacket packet)
1432 {
1433 SilcPacketStream stream = packet->stream;
1434
1435 SILC_LOG_DEBUG(("Freeing packet %p", packet));
1436
1437 /* Check for double free */
1438 SILC_ASSERT(packet->stream != NULL);
1439
1440 packet->stream = NULL;
1441 packet->src_id = packet->dst_id = NULL;
1442 silc_buffer_reset(&packet->buffer);
1443
1444 silc_mutex_lock(stream->sc->engine->lock);
1445
1446 /* Put the packet back to freelist */
1447 silc_list_add(stream->sc->engine->packet_pool, packet);
1448 if (silc_list_count(stream->sc->engine->packet_pool) == 1)
1449 silc_list_start(stream->sc->engine->packet_pool);
1450
1451 silc_mutex_unlock(stream->sc->engine->lock);
1452 }
1453
1454 /****************************** Packet Sending ******************************/
1455
1456 /* Prepare outgoing data buffer for packet sending. Returns the
1457 pointer to that buffer into the `packet'. */
1458
silc_packet_send_prepare(SilcPacketStream stream,SilcUInt32 totlen,SilcHmac hmac,SilcBuffer packet)1459 static inline SilcBool silc_packet_send_prepare(SilcPacketStream stream,
1460 SilcUInt32 totlen,
1461 SilcHmac hmac,
1462 SilcBuffer packet)
1463 {
1464 unsigned char *oldptr;
1465 unsigned int mac_len = hmac ? silc_hmac_len(hmac) : 0;
1466
1467 totlen += mac_len;
1468
1469 /* Allocate more space if needed */
1470 if (silc_unlikely(silc_buffer_taillen(&stream->outbuf) < totlen)) {
1471 if (!silc_buffer_realloc(&stream->outbuf,
1472 silc_buffer_truelen(&stream->outbuf) + totlen))
1473 return FALSE;
1474 }
1475
1476 /* Pull data area for the new packet, and return pointer to the start of
1477 the data area and save the pointer in to the `packet'. MAC is pulled
1478 later after it's computed. */
1479 oldptr = silc_buffer_pull_tail(&stream->outbuf, totlen);
1480 silc_buffer_set(packet, oldptr, totlen);
1481 silc_buffer_push_tail(packet, mac_len);
1482
1483 return TRUE;
1484 }
1485
1486 /* Increments counter when encrypting in counter mode. */
1487
silc_packet_send_ctr_increment(SilcPacketStream stream,SilcCipher cipher,unsigned char * ret_iv)1488 static inline void silc_packet_send_ctr_increment(SilcPacketStream stream,
1489 SilcCipher cipher,
1490 unsigned char *ret_iv)
1491 {
1492 unsigned char *iv = silc_cipher_get_iv(cipher);
1493 SilcUInt32 pc1, pc2;
1494
1495 /* Reset block counter */
1496 memset(iv + 12, 0, 4);
1497
1498 /* If IV Included flag, return the 64-bit IV for inclusion in packet */
1499 if (stream->iv_included) {
1500 /* Get new nonce */
1501 ret_iv[0] = silc_rng_get_byte_fast(stream->sc->engine->rng);
1502 ret_iv[1] = ret_iv[0] + iv[4];
1503 ret_iv[2] = ret_iv[0] ^ ret_iv[1];
1504 ret_iv[3] = ret_iv[0] + ret_iv[2];
1505
1506 /* Increment 32-bit packet counter */
1507 SILC_GET32_MSB(pc1, iv + 8);
1508 pc1++;
1509 SILC_PUT32_MSB(pc1, ret_iv + 4);
1510
1511 SILC_LOG_HEXDUMP(("IV"), ret_iv, 8);
1512
1513 /* Set new nonce to counter block */
1514 memcpy(iv + 4, ret_iv, 8);
1515 } else {
1516 /* Increment 64-bit packet counter */
1517 SILC_GET32_MSB(pc1, iv + 4);
1518 SILC_GET32_MSB(pc2, iv + 8);
1519 if (++pc2 == 0)
1520 ++pc1;
1521 SILC_PUT32_MSB(pc1, iv + 4);
1522 SILC_PUT32_MSB(pc2, iv + 8);
1523 }
1524
1525 SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1526 }
1527
1528 /* Internal routine to assemble outgoing packet. Assembles and encryptes
1529 the packet. The silc_packet_stream_write needs to be called to send it
1530 after this returns TRUE. */
1531
silc_packet_send_raw(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,SilcIdType src_id_type,unsigned char * src_id,SilcUInt32 src_id_len,SilcIdType dst_id_type,unsigned char * dst_id,SilcUInt32 dst_id_len,const unsigned char * data,SilcUInt32 data_len,SilcCipher cipher,SilcHmac hmac)1532 static inline SilcBool silc_packet_send_raw(SilcPacketStream stream,
1533 SilcPacketType type,
1534 SilcPacketFlags flags,
1535 SilcIdType src_id_type,
1536 unsigned char *src_id,
1537 SilcUInt32 src_id_len,
1538 SilcIdType dst_id_type,
1539 unsigned char *dst_id,
1540 SilcUInt32 dst_id_len,
1541 const unsigned char *data,
1542 SilcUInt32 data_len,
1543 SilcCipher cipher,
1544 SilcHmac hmac)
1545 {
1546 unsigned char tmppad[SILC_PACKET_MAX_PADLEN], iv[33], psn[4];
1547 int block_len = (cipher ? silc_cipher_get_block_len(cipher) : 0);
1548 int i, enclen, truelen, padlen = 0, ivlen = 0, psnlen = 0;
1549 SilcBool ctr;
1550 SilcBufferStruct packet;
1551
1552 SILC_LOG_DEBUG(("Sending packet %s (%d) flags %d, src %d dst %d, "
1553 "data len %d", silc_get_packet_name(type), stream->send_psn,
1554 flags, src_id_type, dst_id_type, data_len));
1555
1556 /* Get the true length of the packet. This is saved as payload length
1557 into the packet header. This does not include the length of the
1558 padding. */
1559 data_len = SILC_PACKET_DATALEN(data_len, (SILC_PACKET_HEADER_LEN +
1560 src_id_len + dst_id_len));
1561 enclen = truelen = (data_len + SILC_PACKET_HEADER_LEN +
1562 src_id_len + dst_id_len);
1563
1564 /* If using CTR mode, increment the counter */
1565 ctr = (cipher && silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR);
1566 if (ctr) {
1567 silc_packet_send_ctr_increment(stream, cipher, iv + 1);
1568
1569 /* If IV is included, the SID, IV and sequence number is added to packet */
1570 if (stream->iv_included && cipher) {
1571 psnlen = sizeof(psn);
1572 ivlen = 8 + 1;
1573 iv[0] = stream->sid;
1574 }
1575 } else {
1576 /* If IV is included, the SID, IV and sequence number is added to packet */
1577 if (stream->iv_included && cipher) {
1578 psnlen = sizeof(psn);
1579 ivlen = block_len + 1;
1580 iv[0] = stream->sid;
1581 memcpy(iv + 1, silc_cipher_get_iv(cipher), block_len);
1582 }
1583 }
1584
1585 /* We automatically figure out the packet structure from the packet
1586 type and flags, and calculate correct length. Private messages with
1587 private keys and channel messages are special packets as their
1588 payload is encrypted already. */
1589 if (type == SILC_PACKET_PRIVATE_MESSAGE &&
1590 flags & SILC_PACKET_FLAG_PRIVMSG_KEY) {
1591 /* Padding is calculated from header + IDs */
1592 if (!ctr)
1593 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1594 psnlen), block_len, padlen);
1595
1596 /* Length to encrypt, header + IDs + padding. */
1597 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1598 padlen + psnlen);
1599
1600 } else if (type == SILC_PACKET_CHANNEL_MESSAGE) {
1601 if (stream->sc->engine->local_is_router && stream->is_router) {
1602 /* Channel messages between routers are encrypted as normal packets.
1603 Padding is calculated from true length of the packet. */
1604 if (!ctr)
1605 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1606
1607 enclen += padlen + psnlen;
1608 } else {
1609 /* Padding is calculated from header + IDs */
1610 if (!ctr)
1611 SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1612 psnlen), block_len, padlen);
1613
1614 /* Length to encrypt, header + IDs + padding. */
1615 enclen = (SILC_PACKET_HEADER_LEN + src_id_len + dst_id_len +
1616 padlen + psnlen);
1617 }
1618 } else {
1619 /* Padding is calculated from true length of the packet */
1620 if (flags & SILC_PACKET_FLAG_LONG_PAD)
1621 SILC_PACKET_PADLEN_MAX(truelen + psnlen, block_len, padlen);
1622 else if (!ctr)
1623 SILC_PACKET_PADLEN(truelen + psnlen, block_len, padlen);
1624
1625 enclen += padlen + psnlen;
1626 }
1627
1628 /* Remove implementation specific flags */
1629 flags &= ~(SILC_PACKET_FLAG_LONG_PAD);
1630
1631 /* Get random padding */
1632 for (i = 0; i < padlen; i++) tmppad[i] =
1633 silc_rng_get_byte_fast(stream->sc->engine->rng);
1634
1635 silc_mutex_lock(stream->lock);
1636
1637 /* Get packet pointer from the outgoing buffer */
1638 if (silc_unlikely(!silc_packet_send_prepare(stream, truelen + padlen + ivlen
1639 + psnlen, hmac, &packet))) {
1640 SILC_LOG_ERROR(("Error preparing for packet sending"));
1641 silc_mutex_unlock(stream->lock);
1642 return FALSE;
1643 }
1644
1645 SILC_PUT32_MSB(stream->send_psn, psn);
1646
1647 /* Create the packet. This creates the SILC header, adds padding, and
1648 the actual packet data. */
1649 i = silc_buffer_format(&packet,
1650 SILC_STR_DATA(iv, ivlen),
1651 SILC_STR_DATA(psn, psnlen),
1652 SILC_STR_UI_SHORT(truelen),
1653 SILC_STR_UI_CHAR(flags),
1654 SILC_STR_UI_CHAR(type),
1655 SILC_STR_UI_CHAR(padlen),
1656 SILC_STR_UI_CHAR(0),
1657 SILC_STR_UI_CHAR(src_id_len),
1658 SILC_STR_UI_CHAR(dst_id_len),
1659 SILC_STR_UI_CHAR(src_id_type),
1660 SILC_STR_DATA(src_id, src_id_len),
1661 SILC_STR_UI_CHAR(dst_id_type),
1662 SILC_STR_DATA(dst_id, dst_id_len),
1663 SILC_STR_DATA(tmppad, padlen),
1664 SILC_STR_DATA(data, data_len),
1665 SILC_STR_END);
1666 if (silc_unlikely(i < 0)) {
1667 SILC_LOG_ERROR(("Error encoding outgoing packet"));
1668 silc_mutex_unlock(stream->lock);
1669 return FALSE;
1670 }
1671
1672 SILC_LOG_HEXDUMP(("Assembled packet, len %d", silc_buffer_len(&packet)),
1673 silc_buffer_data(&packet), silc_buffer_len(&packet));
1674
1675 /* Encrypt the packet */
1676 if (silc_likely(cipher)) {
1677 SILC_LOG_DEBUG(("Encrypting packet"));
1678 silc_cipher_set_iv(cipher, NULL);
1679 if (silc_unlikely(!silc_cipher_encrypt(cipher, packet.data + ivlen,
1680 packet.data + ivlen, enclen,
1681 NULL))) {
1682 SILC_LOG_ERROR(("Packet encryption failed"));
1683 silc_mutex_unlock(stream->lock);
1684 return FALSE;
1685 }
1686 }
1687
1688 /* Compute HMAC */
1689 if (silc_likely(hmac)) {
1690 SilcUInt32 mac_len;
1691
1692 /* MAC is computed from the entire encrypted packet data, and put
1693 to the end of the packet. */
1694 silc_hmac_init(hmac);
1695 silc_hmac_update(hmac, psn, sizeof(psn));
1696 silc_hmac_update(hmac, packet.data, silc_buffer_len(&packet));
1697 silc_hmac_final(hmac, packet.tail, &mac_len);
1698 silc_buffer_pull_tail(&packet, mac_len);
1699 stream->send_psn++;
1700 }
1701
1702 return TRUE;
1703 }
1704
1705 /* Sends a packet */
1706
silc_packet_send(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,const unsigned char * data,SilcUInt32 data_len)1707 SilcBool silc_packet_send(SilcPacketStream stream,
1708 SilcPacketType type, SilcPacketFlags flags,
1709 const unsigned char *data, SilcUInt32 data_len)
1710 {
1711 SilcBool ret;
1712
1713 ret = silc_packet_send_raw(stream, type, flags,
1714 stream->src_id_type,
1715 stream->src_id,
1716 stream->src_id_len,
1717 stream->dst_id_type,
1718 stream->dst_id,
1719 stream->dst_id_len,
1720 data, data_len,
1721 stream->send_key[0],
1722 stream->send_hmac[0]);
1723
1724 /* Write the packet to the stream */
1725 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1726 }
1727
1728 /* Sends a packet, extended routine */
1729
silc_packet_send_ext(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,SilcIdType src_id_type,void * src_id,SilcIdType dst_id_type,void * dst_id,const unsigned char * data,SilcUInt32 data_len,SilcCipher cipher,SilcHmac hmac)1730 SilcBool silc_packet_send_ext(SilcPacketStream stream,
1731 SilcPacketType type, SilcPacketFlags flags,
1732 SilcIdType src_id_type, void *src_id,
1733 SilcIdType dst_id_type, void *dst_id,
1734 const unsigned char *data, SilcUInt32 data_len,
1735 SilcCipher cipher, SilcHmac hmac)
1736 {
1737 unsigned char src_id_data[32], dst_id_data[32];
1738 SilcUInt32 src_id_len, dst_id_len;
1739 SilcBool ret;
1740
1741 if (src_id)
1742 if (!silc_id_id2str(src_id, src_id_type, src_id_data,
1743 sizeof(src_id_data), &src_id_len))
1744 return FALSE;
1745 if (dst_id)
1746 if (!silc_id_id2str(dst_id, dst_id_type, dst_id_data,
1747 sizeof(dst_id_data), &dst_id_len))
1748 return FALSE;
1749
1750 ret = silc_packet_send_raw(stream, type, flags,
1751 src_id ? src_id_type : stream->src_id_type,
1752 src_id ? src_id_data : stream->src_id,
1753 src_id ? src_id_len : stream->src_id_len,
1754 dst_id ? dst_id_type : stream->dst_id_type,
1755 dst_id ? dst_id_data : stream->dst_id,
1756 dst_id ? dst_id_len : stream->dst_id_len,
1757 data, data_len,
1758 cipher ? cipher : stream->send_key[0],
1759 hmac ? hmac : stream->send_hmac[0]);
1760
1761 /* Write the packet to the stream */
1762 return ret ? silc_packet_stream_write(stream, FALSE) : FALSE;
1763 }
1764
1765 /* Sends packet after formatting the arguments to buffer */
1766
silc_packet_send_va(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,...)1767 SilcBool silc_packet_send_va(SilcPacketStream stream,
1768 SilcPacketType type, SilcPacketFlags flags, ...)
1769 {
1770 SilcBufferStruct buf;
1771 SilcBool ret;
1772 va_list va;
1773
1774 va_start(va, flags);
1775
1776 memset(&buf, 0, sizeof(buf));
1777 if (silc_buffer_format_vp(&buf, va) < 0) {
1778 va_end(va);
1779 return FALSE;
1780 }
1781
1782 ret = silc_packet_send(stream, type, flags, silc_buffer_data(&buf),
1783 silc_buffer_len(&buf));
1784
1785 silc_buffer_purge(&buf);
1786 va_end(va);
1787
1788 return ret;
1789 }
1790
1791 /* Sends packet after formatting the arguments to buffer, extended routine */
1792
silc_packet_send_va_ext(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,SilcIdType src_id_type,void * src_id,SilcIdType dst_id_type,void * dst_id,SilcCipher cipher,SilcHmac hmac,...)1793 SilcBool silc_packet_send_va_ext(SilcPacketStream stream,
1794 SilcPacketType type, SilcPacketFlags flags,
1795 SilcIdType src_id_type, void *src_id,
1796 SilcIdType dst_id_type, void *dst_id,
1797 SilcCipher cipher, SilcHmac hmac, ...)
1798 {
1799 SilcBufferStruct buf;
1800 SilcBool ret;
1801 va_list va;
1802
1803 va_start(va, hmac);
1804
1805 memset(&buf, 0, sizeof(buf));
1806 if (silc_buffer_format_vp(&buf, va) < 0) {
1807 va_end(va);
1808 return FALSE;
1809 }
1810
1811 ret = silc_packet_send_ext(stream, type, flags, src_id_type, src_id,
1812 dst_id_type, dst_id, silc_buffer_data(&buf),
1813 silc_buffer_len(&buf), cipher, hmac);
1814
1815 silc_buffer_purge(&buf);
1816 va_end(va);
1817
1818 return ret;
1819 }
1820
1821 /***************************** Packet Receiving *****************************/
1822
1823 /* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
1824
silc_packet_check_mac(SilcHmac hmac,const unsigned char * data,SilcUInt32 data_len,const unsigned char * packet_mac,const unsigned char * packet_seq,SilcUInt32 sequence)1825 static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
1826 const unsigned char *data,
1827 SilcUInt32 data_len,
1828 const unsigned char *packet_mac,
1829 const unsigned char *packet_seq,
1830 SilcUInt32 sequence)
1831 {
1832 /* Check MAC */
1833 if (silc_likely(hmac)) {
1834 unsigned char mac[32], psn[4];
1835 SilcUInt32 mac_len;
1836
1837 SILC_LOG_DEBUG(("Verifying MAC"));
1838
1839 /* Compute HMAC of packet */
1840 silc_hmac_init(hmac);
1841
1842 if (!packet_seq) {
1843 SILC_PUT32_MSB(sequence, psn);
1844 silc_hmac_update(hmac, psn, 4);
1845 } else
1846 silc_hmac_update(hmac, packet_seq, 4);
1847
1848 silc_hmac_update(hmac, data, data_len);
1849 silc_hmac_final(hmac, mac, &mac_len);
1850
1851 /* Compare the MAC's */
1852 if (silc_unlikely(memcmp(packet_mac, mac, mac_len))) {
1853 SILC_LOG_DEBUG(("MAC failed"));
1854 return FALSE;
1855 }
1856
1857 SILC_LOG_DEBUG(("MAC is Ok"));
1858 }
1859
1860 return TRUE;
1861 }
1862
1863 /* Increments/sets counter when decrypting in counter mode. */
1864
silc_packet_receive_ctr_increment(SilcPacketStream stream,unsigned char * iv,unsigned char * packet_iv)1865 static inline void silc_packet_receive_ctr_increment(SilcPacketStream stream,
1866 unsigned char *iv,
1867 unsigned char *packet_iv)
1868 {
1869 SilcUInt32 pc1, pc2;
1870
1871 /* If IV Included flag, set the IV from packet to block counter. */
1872 if (stream->iv_included) {
1873 memcpy(iv + 4, packet_iv, 8);
1874 } else {
1875 /* Increment 64-bit packet counter. */
1876 SILC_GET32_MSB(pc1, iv + 4);
1877 SILC_GET32_MSB(pc2, iv + 8);
1878 if (++pc2 == 0)
1879 ++pc1;
1880 SILC_PUT32_MSB(pc1, iv + 4);
1881 SILC_PUT32_MSB(pc2, iv + 8);
1882 }
1883
1884 /* Reset block counter */
1885 memset(iv + 12, 0, 4);
1886
1887 SILC_LOG_HEXDUMP(("Counter Block"), iv, 16);
1888 }
1889
1890 /* Return special packet's encrypted length */
1891
silc_packet_special_len(unsigned char * data)1892 static inline int silc_packet_special_len(unsigned char *data)
1893 {
1894 return (((SilcUInt8)data[4] + (SilcUInt8)data[6] +
1895 (SilcUInt8)data[7] + SILC_PACKET_HEADER_LEN));
1896 }
1897
1898 /* Decrypts SILC packet. Handles both normal and special packet decryption.
1899 Return 0 when packet is normal and 1 when it it special, -1 on error. */
1900
silc_packet_decrypt(SilcCipher cipher,SilcHmac hmac,SilcUInt32 sequence,SilcBuffer buffer,SilcBool normal)1901 static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
1902 SilcUInt32 sequence, SilcBuffer buffer,
1903 SilcBool normal)
1904 {
1905 if (normal == TRUE) {
1906 if (silc_likely(cipher)) {
1907 /* Decrypt rest of the packet */
1908 SILC_LOG_DEBUG(("Decrypting the packet"));
1909 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1910 buffer->data,
1911 silc_buffer_len(buffer), NULL)))
1912 return -1;
1913 }
1914 return 0;
1915
1916 } else {
1917 /* Decrypt rest of the header plus padding */
1918 if (silc_likely(cipher)) {
1919 SilcUInt16 len;
1920 SilcUInt32 block_len = silc_cipher_get_block_len(cipher);
1921
1922 SILC_LOG_DEBUG(("Decrypting the header"));
1923
1924 /* Padding length + src id len + dst id len + header length - 16
1925 bytes already decrypted, gives the rest of the encrypted packet */
1926 silc_buffer_push(buffer, block_len);
1927 len = silc_packet_special_len(buffer->data) - block_len;
1928 silc_buffer_pull(buffer, block_len);
1929
1930 if (silc_unlikely(len > silc_buffer_len(buffer))) {
1931 SILC_LOG_ERROR(("Garbage in header of packet, bad packet length, "
1932 "packet dropped"));
1933 return -1;
1934 }
1935 if (silc_unlikely(!silc_cipher_decrypt(cipher, buffer->data,
1936 buffer->data, len, NULL)))
1937 return -1;
1938 }
1939
1940 return 1;
1941 }
1942 }
1943
1944 /* Parses the packet. This is called when a whole packet is ready to be
1945 parsed. The buffer sent must be already decrypted before calling this
1946 function. */
1947
silc_packet_parse(SilcPacket packet)1948 static inline SilcBool silc_packet_parse(SilcPacket packet)
1949 {
1950 SilcBuffer buffer = &packet->buffer;
1951 SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
1952 SilcUInt8 src_id_len, dst_id_len, src_id_type, dst_id_type;
1953 int ret;
1954
1955 SILC_LOG_DEBUG(("Parsing incoming packet"));
1956
1957 /* Parse the buffer. This parses the SILC header of the packet. */
1958 ret = silc_buffer_unformat(buffer,
1959 SILC_STR_ADVANCE,
1960 SILC_STR_OFFSET(6),
1961 SILC_STR_UI_CHAR(&src_id_len),
1962 SILC_STR_UI_CHAR(&dst_id_len),
1963 SILC_STR_UI_CHAR(&src_id_type),
1964 SILC_STR_END);
1965 if (silc_unlikely(ret == -1)) {
1966 if (!packet->stream->udp &&
1967 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1968 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1969 return FALSE;
1970 }
1971
1972 if (silc_unlikely(src_id_len > SILC_PACKET_MAX_ID_LEN ||
1973 dst_id_len > SILC_PACKET_MAX_ID_LEN)) {
1974 if (!packet->stream->udp &&
1975 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1976 SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
1977 packet->src_id_len, packet->dst_id_len));
1978 return FALSE;
1979 }
1980
1981 ret = silc_buffer_unformat(buffer,
1982 SILC_STR_ADVANCE,
1983 SILC_STR_DATA(&packet->src_id, src_id_len),
1984 SILC_STR_UI_CHAR(&dst_id_type),
1985 SILC_STR_DATA(&packet->dst_id, dst_id_len),
1986 SILC_STR_OFFSET(padlen),
1987 SILC_STR_END);
1988 if (silc_unlikely(ret == -1)) {
1989 if (!packet->stream->udp &&
1990 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1991 SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
1992 return FALSE;
1993 }
1994
1995 if (silc_unlikely(src_id_type > SILC_ID_CHANNEL ||
1996 dst_id_type > SILC_ID_CHANNEL)) {
1997 if (!packet->stream->udp &&
1998 !silc_socket_stream_is_udp(packet->stream->stream, NULL))
1999 SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
2000 src_id_type, dst_id_type));
2001 return FALSE;
2002 }
2003
2004 packet->src_id_len = src_id_len;
2005 packet->dst_id_len = dst_id_len;
2006 packet->src_id_type = src_id_type;
2007 packet->dst_id_type = dst_id_type;
2008
2009 SILC_LOG_HEXDUMP(("Parsed packet, len %d", silc_buffer_headlen(buffer) +
2010 silc_buffer_len(buffer)), buffer->head,
2011 silc_buffer_headlen(buffer) + silc_buffer_len(buffer));
2012
2013 SILC_LOG_DEBUG(("Incoming packet type: %d (%s), flags %d", packet->type,
2014 silc_get_packet_name(packet->type), packet->flags));
2015
2016 return TRUE;
2017 }
2018
2019 /* Dispatch packet to application. Called with stream->lock locked.
2020 Returns FALSE if the stream was destroyed while dispatching a packet. */
2021
silc_packet_dispatch(SilcPacket packet,SilcPacketReceiveCb ignore_handler)2022 static SilcBool silc_packet_dispatch(SilcPacket packet,
2023 SilcPacketReceiveCb ignore_handler)
2024 {
2025 SilcPacketStream stream = packet->stream;
2026 SilcPacketProcess p;
2027 SilcBool default_sent = FALSE;
2028 SilcPacketType *pt;
2029
2030 /* Dispatch packet to all packet processors that want it */
2031
2032 if (silc_likely(!stream->process)) {
2033 /* Send to default processor as no others exist */
2034 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
2035 silc_mutex_unlock(stream->lock);
2036 if (silc_unlikely(!stream->sc->engine->callbacks->
2037 packet_receive(stream->sc->engine, stream, packet,
2038 stream->sc->engine->callback_context,
2039 stream->stream_context)))
2040 silc_packet_free(packet);
2041 silc_mutex_lock(stream->lock);
2042 return stream->destroyed == FALSE;
2043 }
2044
2045 silc_dlist_start(stream->process);
2046 while ((p = silc_dlist_get(stream->process)) != SILC_LIST_END) {
2047
2048 /* If priority is 0 or less, we send to default processor first
2049 because default processor has 0 priority */
2050 if (!default_sent && p->priority <= 0) {
2051 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
2052 default_sent = TRUE;
2053 silc_mutex_unlock(stream->lock);
2054 if (stream->sc->engine->callbacks->
2055 packet_receive(stream->sc->engine, stream, packet,
2056 stream->sc->engine->callback_context,
2057 stream->stream_context)) {
2058 silc_mutex_lock(stream->lock);
2059 return stream->destroyed == FALSE;
2060 }
2061 silc_mutex_lock(stream->lock);
2062 }
2063
2064 /* Send to processor */
2065 if (!p->types) {
2066 /* Send all packet types */
2067 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
2068 silc_mutex_unlock(stream->lock);
2069 if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
2070 p->callback_context,
2071 stream->stream_context)) {
2072 silc_mutex_lock(stream->lock);
2073 return stream->destroyed == FALSE;
2074 }
2075 silc_mutex_lock(stream->lock);
2076 } else {
2077 /* Send specific types */
2078 for (pt = p->types; *pt; pt++) {
2079 if (*pt != packet->type ||
2080 ignore_handler == p->callbacks->packet_receive)
2081 continue;
2082 SILC_LOG_DEBUG(("Dispatching packet to %p callbacks", p->callbacks));
2083 silc_mutex_unlock(stream->lock);
2084 if (p->callbacks->packet_receive(stream->sc->engine, stream, packet,
2085 p->callback_context,
2086 stream->stream_context)) {
2087 silc_mutex_lock(stream->lock);
2088 return stream->destroyed == FALSE;
2089 }
2090 silc_mutex_lock(stream->lock);
2091 break;
2092 }
2093 }
2094 }
2095
2096 if (!default_sent) {
2097 /* Send to default processor as it has not been sent yet */
2098 SILC_LOG_DEBUG(("Dispatching packet to default callbacks"));
2099 silc_mutex_unlock(stream->lock);
2100 if (stream->sc->engine->callbacks->
2101 packet_receive(stream->sc->engine, stream, packet,
2102 stream->sc->engine->callback_context,
2103 stream->stream_context)) {
2104 silc_mutex_lock(stream->lock);
2105 return stream->destroyed == FALSE;
2106 }
2107 silc_mutex_lock(stream->lock);
2108 }
2109
2110 /* If we got here, no one wanted the packet, so drop it */
2111 silc_packet_free(packet);
2112 return stream->destroyed == FALSE;
2113 }
2114
2115 /* Process incoming data and parse packets. Called with stream->lock
2116 locked. */
2117
silc_packet_read_process(SilcPacketStream stream)2118 static void silc_packet_read_process(SilcPacketStream stream)
2119 {
2120 SilcBuffer inbuf;
2121 SilcCipher cipher;
2122 SilcHmac hmac;
2123 SilcPacket packet;
2124 SilcUInt8 sid, flags, type;
2125 SilcUInt16 packetlen;
2126 SilcUInt32 paddedlen, mac_len, block_len, ivlen, psnlen;
2127 unsigned char tmp[SILC_PACKET_MIN_HEADER_LEN], *header;
2128 unsigned char iv[SILC_CIPHER_MAX_IV_SIZE], *packet_seq = NULL;
2129 SilcBool normal;
2130 int ret;
2131
2132 /* Get inbuf. If there is already some data for this stream in the buffer
2133 we already have it. Otherwise get the current one from list, it will
2134 include the data. */
2135 inbuf = stream->inbuf;
2136 if (!inbuf) {
2137 silc_dlist_start(stream->sc->inbufs);
2138 inbuf = silc_dlist_get(stream->sc->inbufs);
2139 }
2140
2141 /* Parse the packets from the data */
2142 while (silc_buffer_len(inbuf) > 0) {
2143 ivlen = psnlen = 0;
2144 cipher = stream->receive_key[0];
2145 hmac = stream->receive_hmac[0];
2146 normal = FALSE;
2147
2148 if (silc_unlikely(silc_buffer_len(inbuf) <
2149 (stream->iv_included ? SILC_PACKET_MIN_HEADER_LEN_IV :
2150 SILC_PACKET_MIN_HEADER_LEN))) {
2151 SILC_LOG_DEBUG(("Partial packet in queue, waiting for the rest"));
2152 silc_dlist_del(stream->sc->inbufs, inbuf);
2153 stream->inbuf = inbuf;
2154 return;
2155 }
2156
2157 if (silc_likely(hmac))
2158 mac_len = silc_hmac_len(hmac);
2159 else
2160 mac_len = 0;
2161
2162 /* Decrypt first block of the packet to get the length field out */
2163 if (silc_likely(cipher)) {
2164 block_len = silc_cipher_get_block_len(cipher);
2165
2166 if (stream->iv_included) {
2167 /* SID, IV and sequence number is included in the ciphertext */
2168 sid = (SilcUInt8)inbuf->data[0];
2169
2170 if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR) {
2171 /* Set the CTR mode IV from packet to counter block */
2172 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2173 silc_packet_receive_ctr_increment(stream, iv, inbuf->data + 1);
2174 ivlen = 8 + 1;
2175 } else {
2176 /* Get IV from packet */
2177 memcpy(iv, inbuf->data + 1, block_len);
2178 ivlen = block_len + 1;
2179 }
2180 psnlen = 4;
2181
2182 /* Check SID, and get correct decryption key */
2183 if (sid != stream->sid) {
2184 /* If SID is recent get the previous key and use it */
2185 if (sid > 0 && stream->sid > 0 && stream->sid - 1 == sid &&
2186 stream->receive_key[1] && !stream->receive_hmac[1]) {
2187 cipher = stream->receive_key[1];
2188 hmac = stream->receive_hmac[1];
2189 } else {
2190 /* The SID is unknown, drop rest of the data in buffer */
2191 SILC_LOG_DEBUG(("Unknown Security ID %d in packet, expected %d",
2192 sid, stream->sid));
2193 silc_mutex_unlock(stream->lock);
2194 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_UNKNOWN_SID);
2195 silc_mutex_lock(stream->lock);
2196 goto out;
2197 }
2198 }
2199 } else {
2200 memcpy(iv, silc_cipher_get_iv(cipher), block_len);
2201
2202 /* If using CTR mode, increment the counter */
2203 if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2204 silc_packet_receive_ctr_increment(stream, iv, NULL);
2205 }
2206
2207 if (silc_cipher_get_mode(cipher) == SILC_CIPHER_MODE_CTR)
2208 silc_cipher_set_iv(cipher, NULL);
2209 silc_cipher_decrypt(cipher, inbuf->data + ivlen, tmp, block_len, iv);
2210
2211 header = tmp;
2212 if (stream->iv_included) {
2213 /* Take sequence number from packet */
2214 packet_seq = header;
2215 header += 4;
2216 }
2217 } else {
2218 /* Unencrypted packet */
2219 block_len = SILC_PACKET_MIN_HEADER_LEN;
2220 header = inbuf->data;
2221 }
2222
2223 /* Get packet length and full packet length with padding */
2224 SILC_PACKET_LENGTH(header, packetlen, paddedlen);
2225
2226 /* Parse packet header */
2227 flags = (SilcPacketFlags)header[2];
2228 type = (SilcPacketType)header[3];
2229
2230 if (stream->sc->engine->local_is_router) {
2231 if (type == SILC_PACKET_PRIVATE_MESSAGE &&
2232 (flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2233 normal = FALSE;
2234 else if (type != SILC_PACKET_CHANNEL_MESSAGE ||
2235 (type == SILC_PACKET_CHANNEL_MESSAGE &&
2236 stream->is_router == TRUE))
2237 normal = TRUE;
2238 } else {
2239 if (type == SILC_PACKET_PRIVATE_MESSAGE &&
2240 (flags & SILC_PACKET_FLAG_PRIVMSG_KEY))
2241 normal = FALSE;
2242 else if (type != SILC_PACKET_CHANNEL_MESSAGE)
2243 normal = TRUE;
2244 }
2245
2246 /* Padding sanity checks */
2247 if (cipher && silc_cipher_get_mode(cipher) != SILC_CIPHER_MODE_CTR &&
2248 ((normal && block_len && paddedlen % block_len != 0) ||
2249 (!normal && block_len &&
2250 silc_packet_special_len(header) % block_len != 0))) {
2251 SILC_LOG_DEBUG(("Packet length %d not multiple by cipher block length",
2252 paddedlen));
2253 silc_mutex_unlock(stream->lock);
2254 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2255 silc_mutex_lock(stream->lock);
2256 memset(tmp, 0, sizeof(tmp));
2257 goto out;
2258 }
2259
2260 if (silc_buffer_len(inbuf) < paddedlen + ivlen + mac_len) {
2261 SILC_LOG_DEBUG(("Received partial packet (%d %s flags:%x normal:%d "
2262 "len:%u paddedlen:%u), waiting for the rest (%d bytes)",
2263 type, silc_get_packet_name(type), flags,
2264 normal, packetlen, paddedlen,
2265 paddedlen + mac_len - silc_buffer_len(inbuf)));
2266 memset(tmp, 0, sizeof(tmp));
2267 silc_dlist_del(stream->sc->inbufs, inbuf);
2268 stream->inbuf = inbuf;
2269 return;
2270 }
2271
2272 /* Check MAC of the packet */
2273 if (silc_unlikely(!silc_packet_check_mac(hmac, inbuf->data,
2274 paddedlen + ivlen,
2275 inbuf->data + ivlen +
2276 paddedlen, packet_seq,
2277 stream->receive_psn))) {
2278 silc_mutex_unlock(stream->lock);
2279 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MAC_FAILED);
2280 silc_mutex_lock(stream->lock);
2281 memset(tmp, 0, sizeof(tmp));
2282 goto out;
2283 }
2284
2285 /* Sanity checks */
2286 if (silc_unlikely(packetlen < SILC_PACKET_MIN_LEN)) {
2287 if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
2288 SILC_LOG_ERROR(("Received too short packet"));
2289 silc_mutex_unlock(stream->lock);
2290 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2291 silc_mutex_lock(stream->lock);
2292 memset(tmp, 0, sizeof(tmp));
2293 goto out;
2294 }
2295
2296 /* Get packet */
2297 packet = silc_packet_alloc(stream->sc->engine);
2298 if (silc_unlikely(!packet)) {
2299 silc_mutex_unlock(stream->lock);
2300 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2301 silc_mutex_lock(stream->lock);
2302 memset(tmp, 0, sizeof(tmp));
2303 goto out;
2304 }
2305 packet->stream = stream;
2306 packet->flags = flags;
2307 packet->type = type;
2308
2309 /* Allocate more space to packet buffer, if needed */
2310 if (silc_unlikely(silc_buffer_truelen(&packet->buffer) < paddedlen)) {
2311 if (!silc_buffer_realloc(&packet->buffer,
2312 silc_buffer_truelen(&packet->buffer) +
2313 (paddedlen -
2314 silc_buffer_truelen(&packet->buffer)))) {
2315 silc_mutex_unlock(stream->lock);
2316 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_NO_MEMORY);
2317 silc_mutex_lock(stream->lock);
2318 silc_packet_free(packet);
2319 memset(tmp, 0, sizeof(tmp));
2320 goto out;
2321 }
2322 }
2323
2324 SILC_LOG_HEXDUMP(("Incoming packet (%d) len %d",
2325 stream->receive_psn, paddedlen + ivlen + mac_len),
2326 inbuf->data, paddedlen + ivlen + mac_len);
2327
2328 /* Put the decrypted part, and rest of the encrypted data, and decrypt */
2329 silc_buffer_pull_tail(&packet->buffer, paddedlen);
2330 silc_buffer_put(&packet->buffer, header, block_len - psnlen);
2331 silc_buffer_pull(&packet->buffer, block_len - psnlen);
2332 silc_buffer_put(&packet->buffer, (inbuf->data + ivlen +
2333 psnlen + (block_len - psnlen)),
2334 paddedlen - ivlen - psnlen - (block_len - psnlen));
2335 if (silc_likely(cipher)) {
2336 silc_cipher_set_iv(cipher, iv);
2337 ret = silc_packet_decrypt(cipher, hmac, stream->receive_psn,
2338 &packet->buffer, normal);
2339 if (silc_unlikely(ret < 0)) {
2340 silc_mutex_unlock(stream->lock);
2341 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_DECRYPTION_FAILED);
2342 silc_mutex_lock(stream->lock);
2343 silc_packet_free(packet);
2344 memset(tmp, 0, sizeof(tmp));
2345 goto out;
2346 }
2347
2348 stream->receive_psn++;
2349 }
2350 silc_buffer_push(&packet->buffer, block_len);
2351
2352 /* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
2353 silc_buffer_pull(inbuf, paddedlen + mac_len);
2354
2355 /* Parse the packet */
2356 if (silc_unlikely(!silc_packet_parse(packet))) {
2357 silc_mutex_unlock(stream->lock);
2358 SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
2359 silc_mutex_lock(stream->lock);
2360 silc_packet_free(packet);
2361 memset(tmp, 0, sizeof(tmp));
2362 goto out;
2363 }
2364
2365 /* Dispatch the packet to application */
2366 if (!silc_packet_dispatch(packet, NULL))
2367 break;
2368 }
2369
2370 out:
2371 /* Add inbuf back to free list, if we owned it. */
2372 if (stream->inbuf) {
2373 silc_dlist_add(stream->sc->inbufs, inbuf);
2374 stream->inbuf = NULL;
2375 }
2376
2377 silc_buffer_reset(inbuf);
2378 }
2379
2380 /****************************** Packet Waiting ******************************/
2381
2382 /* Packet wait receive callback */
2383 static SilcBool
2384 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2385 SilcPacketStream stream,
2386 SilcPacket packet,
2387 void *callback_context,
2388 void *stream_context);
2389
2390 /* Packet waiting callbacks */
2391 static const SilcPacketCallbacks silc_packet_wait_cbs =
2392 {
2393 silc_packet_wait_packet_receive, NULL, NULL
2394 };
2395
2396 /* Packet waiting context */
2397 typedef struct {
2398 SilcMutex wait_lock;
2399 SilcCond wait_cond;
2400 SilcList packet_queue;
2401 unsigned char id[28];
2402 unsigned int id_type : 2;
2403 unsigned int id_len : 5;
2404 unsigned int stopped : 1;
2405 } *SilcPacketWait;
2406
2407 /* Packet wait receive callback */
2408
2409 static SilcBool
silc_packet_wait_packet_receive(SilcPacketEngine engine,SilcPacketStream stream,SilcPacket packet,void * callback_context,void * stream_context)2410 silc_packet_wait_packet_receive(SilcPacketEngine engine,
2411 SilcPacketStream stream,
2412 SilcPacket packet,
2413 void *callback_context,
2414 void *stream_context)
2415 {
2416 SilcPacketWait pw = callback_context;
2417
2418 /* If source ID is specified check for it */
2419 if (pw->id_len) {
2420 if (pw->id_type != packet->src_id_type ||
2421 memcmp(pw->id, packet->src_id, pw->id_len))
2422 return FALSE;
2423 }
2424
2425 /* Signal the waiting thread for a new packet */
2426 silc_mutex_lock(pw->wait_lock);
2427
2428 if (silc_unlikely(pw->stopped)) {
2429 silc_mutex_unlock(pw->wait_lock);
2430 return FALSE;
2431 }
2432
2433 silc_list_add(pw->packet_queue, packet);
2434 silc_cond_broadcast(pw->wait_cond);
2435
2436 silc_mutex_unlock(pw->wait_lock);
2437
2438 return TRUE;
2439 }
2440
2441 /* Initialize packet waiting */
2442
silc_packet_wait_init(SilcPacketStream stream,const SilcID * source_id,...)2443 void *silc_packet_wait_init(SilcPacketStream stream,
2444 const SilcID *source_id, ...)
2445 {
2446 SilcPacketWait pw;
2447 SilcBool ret;
2448 va_list ap;
2449
2450 pw = silc_calloc(1, sizeof(*pw));
2451 if (!pw)
2452 return NULL;
2453
2454 /* Allocate mutex and conditional variable */
2455 if (!silc_mutex_alloc(&pw->wait_lock)) {
2456 silc_free(pw);
2457 return NULL;
2458 }
2459 if (!silc_cond_alloc(&pw->wait_cond)) {
2460 silc_mutex_free(pw->wait_lock);
2461 silc_free(pw);
2462 return NULL;
2463 }
2464
2465 /* Link to the packet stream for the requested packet types */
2466 va_start(ap, source_id);
2467 ret = silc_packet_stream_link_va(stream, &silc_packet_wait_cbs, pw,
2468 10000000, ap);
2469 va_end(ap);
2470 if (!ret) {
2471 silc_cond_free(pw->wait_cond);
2472 silc_mutex_free(pw->wait_lock);
2473 silc_free(pw);
2474 return NULL;
2475 }
2476
2477 /* Initialize packet queue */
2478 silc_list_init(pw->packet_queue, struct SilcPacketStruct, next);
2479
2480 if (source_id) {
2481 SilcUInt32 id_len;
2482 silc_id_id2str(SILC_ID_GET_ID(*source_id), source_id->type, pw->id,
2483 sizeof(pw->id), &id_len);
2484 pw->id_type = source_id->type;
2485 pw->id_len = id_len;
2486 }
2487
2488 return (void *)pw;
2489 }
2490
2491 /* Uninitialize packet waiting */
2492
silc_packet_wait_uninit(void * waiter,SilcPacketStream stream)2493 void silc_packet_wait_uninit(void *waiter, SilcPacketStream stream)
2494 {
2495 SilcPacketWait pw = waiter;
2496 SilcPacket packet;
2497
2498 /* Signal any threads to stop waiting */
2499 silc_mutex_lock(pw->wait_lock);
2500 pw->stopped = TRUE;
2501 silc_cond_broadcast(pw->wait_cond);
2502 silc_mutex_unlock(pw->wait_lock);
2503 silc_thread_yield();
2504
2505 /* Re-acquire lock and free resources */
2506 silc_mutex_lock(pw->wait_lock);
2507 silc_packet_stream_unlink(stream, &silc_packet_wait_cbs, pw);
2508
2509 /* Free any remaining packets */
2510 silc_list_start(pw->packet_queue);
2511 while ((packet = silc_list_get(pw->packet_queue)) != SILC_LIST_END)
2512 silc_packet_free(packet);
2513
2514 silc_mutex_unlock(pw->wait_lock);
2515 silc_cond_free(pw->wait_cond);
2516 silc_mutex_free(pw->wait_lock);
2517 silc_free(pw);
2518 }
2519
2520 /* Blocks thread until a packet has been received. */
2521
silc_packet_wait(void * waiter,int timeout,SilcPacket * return_packet)2522 int silc_packet_wait(void *waiter, int timeout, SilcPacket *return_packet)
2523 {
2524 SilcPacketWait pw = waiter;
2525 SilcBool ret = FALSE;
2526
2527 silc_mutex_lock(pw->wait_lock);
2528
2529 /* Wait here until packet has arrived */
2530 while (silc_list_count(pw->packet_queue) == 0) {
2531 if (silc_unlikely(pw->stopped)) {
2532 silc_mutex_unlock(pw->wait_lock);
2533 return -1;
2534 }
2535 ret = silc_cond_timedwait(pw->wait_cond, pw->wait_lock, timeout);
2536 }
2537
2538 /* Return packet */
2539 silc_list_start(pw->packet_queue);
2540 *return_packet = silc_list_get(pw->packet_queue);
2541 silc_list_del(pw->packet_queue, *return_packet);
2542
2543 silc_mutex_unlock(pw->wait_lock);
2544
2545 return ret == TRUE ? 1 : 0;
2546 }
2547
2548 /************************** Packet Stream Wrapper ***************************/
2549
2550 /* Packet stream wrapper receive callback */
2551 static SilcBool
2552 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2553 SilcPacketStream stream,
2554 SilcPacket packet,
2555 void *callback_context,
2556 void *stream_context);
2557
2558 const SilcStreamOps silc_packet_stream_ops;
2559
2560 /* Packet stream wrapper context */
2561 typedef struct {
2562 const SilcStreamOps *ops;
2563 SilcPacketStream stream;
2564 SilcMutex lock;
2565 void *waiter; /* Waiter context in blocking mode */
2566 SilcPacketWrapCoder coder;
2567 void *coder_context;
2568 SilcBuffer encbuf;
2569 SilcStreamNotifier callback;
2570 void *context;
2571 SilcList in_queue;
2572 SilcPacketType type;
2573 SilcPacketFlags flags;
2574 void *src_id;
2575 void *dst_id;
2576 SilcIdType src_id_type;
2577 SilcIdType dst_id_type;
2578 unsigned int closed : 1;
2579 unsigned int blocking : 1;
2580 unsigned int read_more : 1;
2581 } *SilcPacketWrapperStream;
2582
2583 /* Packet wrapper callbacks */
2584 static const SilcPacketCallbacks silc_packet_wrap_cbs =
2585 {
2586 silc_packet_wrap_packet_receive, NULL, NULL
2587 };
2588
2589 /* Packet stream wrapper receive callback, non-blocking mode */
2590
2591 static SilcBool
silc_packet_wrap_packet_receive(SilcPacketEngine engine,SilcPacketStream stream,SilcPacket packet,void * callback_context,void * stream_context)2592 silc_packet_wrap_packet_receive(SilcPacketEngine engine,
2593 SilcPacketStream stream,
2594 SilcPacket packet,
2595 void *callback_context,
2596 void *stream_context)
2597 {
2598 SilcPacketWrapperStream pws = callback_context;
2599 SilcID id;
2600
2601 if (pws->closed || !pws->callback)
2602 return FALSE;
2603
2604 /* If dst_id was set, the incoming packet must use that id as its
2605 source id. This will not work if the id is channel id because
2606 the source is never the channel id, but will work with other ids. */
2607 if ((pws->dst_id && pws->dst_id_type != SILC_ID_CHANNEL)) {
2608 silc_id_str2id2(packet->src_id, packet->src_id_len,
2609 packet->src_id_type, &id);
2610 if (!SILC_ID_COMPARE_TYPE(pws->dst_id, SILC_ID_GET_ID(id),
2611 packet->src_id_len)) {
2612 SILC_LOG_DEBUG(("Packet is not from wanted sender"));
2613 return FALSE;
2614 }
2615 }
2616
2617 silc_mutex_lock(pws->lock);
2618 silc_list_add(pws->in_queue, packet);
2619 silc_mutex_unlock(pws->lock);
2620
2621 /* Call notifier callback */
2622 pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2623
2624 return TRUE;
2625 }
2626
2627 /* Task callback to notify more data is available for reading */
2628
SILC_TASK_CALLBACK(silc_packet_wrap_read_more)2629 SILC_TASK_CALLBACK(silc_packet_wrap_read_more)
2630 {
2631 SilcPacketWrapperStream pws = context;
2632
2633 if (pws->closed || !pws->callback)
2634 return;
2635
2636 /* Call notifier callback */
2637 pws->callback((SilcStream)pws, SILC_STREAM_CAN_READ, pws->context);
2638 }
2639
2640 /* Read SILC packet */
2641
silc_packet_wrap_read(SilcStream stream,unsigned char * buf,SilcUInt32 buf_len)2642 int silc_packet_wrap_read(SilcStream stream, unsigned char *buf,
2643 SilcUInt32 buf_len)
2644 {
2645 SilcPacketWrapperStream pws = stream;
2646 SilcPacket packet;
2647 SilcBool read_more = FALSE, ret = TRUE;
2648 int len;
2649
2650 if (pws->closed)
2651 return -2;
2652
2653 if (pws->blocking) {
2654 /* Block until packet is received */
2655 if ((silc_packet_wait(pws->waiter, 0, &packet)) < 0)
2656 return -2;
2657 if (pws->closed)
2658 return -2;
2659 } else {
2660 /* Non-blocking mode */
2661 silc_mutex_lock(pws->lock);
2662 if (!silc_list_count(pws->in_queue)) {
2663 silc_mutex_unlock(pws->lock);
2664 return -1;
2665 }
2666
2667 silc_list_start(pws->in_queue);
2668 packet = silc_list_get(pws->in_queue);
2669 silc_list_del(pws->in_queue, packet);
2670 silc_mutex_unlock(pws->lock);
2671 }
2672
2673 /* Call decoder if set */
2674 if (pws->coder && !pws->read_more)
2675 ret = pws->coder(stream, SILC_STREAM_CAN_READ, &packet->buffer,
2676 pws->coder_context);
2677
2678 if (!ret) {
2679 /* If error occurred during decoding (or handler doesn't want this
2680 packet), we'll reprocess this packet and try to give it to some
2681 other handler that may want it. For this stream nothing was
2682 received. */
2683 silc_packet_dispatch(packet, silc_packet_wrap_packet_receive);
2684 return -1;
2685 }
2686
2687 len = silc_buffer_len(&packet->buffer);
2688 if (len > buf_len) {
2689 len = buf_len;
2690 read_more = TRUE;
2691 }
2692
2693 /* Read data */
2694 memcpy(buf, packet->buffer.data, len);
2695
2696 if (read_more && !pws->blocking) {
2697 /* More data will be available (in blocking mode not supported). */
2698 silc_buffer_pull(&packet->buffer, len);
2699 silc_list_insert(pws->in_queue, NULL, packet);
2700 silc_schedule_task_add_timeout(pws->stream->sc->schedule,
2701 silc_packet_wrap_read_more, pws, 0, 0);
2702 pws->read_more = TRUE;
2703 return len;
2704 }
2705
2706 pws->read_more = FALSE;
2707 silc_packet_free(packet);
2708 return len;
2709 }
2710
2711 /* Write SILC packet */
2712
silc_packet_wrap_write(SilcStream stream,const unsigned char * data,SilcUInt32 data_len)2713 int silc_packet_wrap_write(SilcStream stream, const unsigned char *data,
2714 SilcUInt32 data_len)
2715 {
2716 SilcPacketWrapperStream pws = stream;
2717 SilcBool ret = TRUE;
2718
2719 if (!pws->coder) {
2720 if (!silc_packet_send_ext(pws->stream, pws->type, pws->flags,
2721 pws->src_id_type, pws->src_id,
2722 pws->dst_id_type, pws->dst_id,
2723 data, data_len, NULL, NULL))
2724 return -2;
2725 return data_len;
2726 }
2727
2728 silc_buffer_reset(pws->encbuf);
2729 if (!silc_buffer_enlarge(pws->encbuf, data_len + 16))
2730 return -2;
2731 silc_buffer_pull(pws->encbuf, 16); /* Room for adding headers */
2732 silc_buffer_put(pws->encbuf, data, data_len);
2733
2734 ret = pws->coder(stream, SILC_STREAM_CAN_WRITE, pws->encbuf,
2735 pws->coder_context);
2736
2737 /* Send the SILC packet */
2738 if (ret) {
2739 if (!silc_packet_send_ext(pws->stream, pws->type, pws->flags,
2740 pws->src_id_type, pws->src_id,
2741 pws->dst_id_type, pws->dst_id,
2742 silc_buffer_datalen(pws->encbuf),
2743 NULL, NULL))
2744 return -2;
2745 return data_len;
2746 }
2747
2748 /* Error */
2749 return -2;
2750 }
2751
2752 /* Close stream */
2753
silc_packet_wrap_close(SilcStream stream)2754 SilcBool silc_packet_wrap_close(SilcStream stream)
2755 {
2756 SilcPacketWrapperStream pws = stream;
2757
2758 if (pws->closed)
2759 return TRUE;
2760
2761 if (pws->blocking) {
2762 /* Close packet waiter */
2763 silc_packet_wait_uninit(pws->waiter, pws->stream);
2764 } else {
2765 /* Unlink */
2766 if (pws->callback)
2767 silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2768 }
2769 pws->closed = TRUE;
2770
2771 return TRUE;
2772 }
2773
2774 /* Destroy wrapper stream */
2775
silc_packet_wrap_destroy(SilcStream stream)2776 void silc_packet_wrap_destroy(SilcStream stream)
2777
2778 {
2779 SilcPacketWrapperStream pws = stream;
2780 SilcPacket packet;
2781
2782 SILC_LOG_DEBUG(("Destroying wrapped packet stream %p", pws));
2783
2784 silc_stream_close(stream);
2785 silc_list_start(pws->in_queue);
2786 while ((packet = silc_list_get(pws->in_queue)))
2787 silc_packet_free(packet);
2788 if (pws->lock)
2789 silc_mutex_free(pws->lock);
2790 if (pws->encbuf)
2791 silc_buffer_free(pws->encbuf);
2792 silc_packet_stream_unref(pws->stream);
2793
2794 silc_free(pws);
2795 }
2796
2797 /* Link stream to receive packets */
2798
silc_packet_wrap_notifier(SilcStream stream,SilcSchedule schedule,SilcStreamNotifier callback,void * context)2799 SilcBool silc_packet_wrap_notifier(SilcStream stream,
2800 SilcSchedule schedule,
2801 SilcStreamNotifier callback,
2802 void *context)
2803 {
2804 SilcPacketWrapperStream pws = stream;
2805
2806 if (pws->closed || pws->blocking)
2807 return FALSE;
2808
2809 /* Link to receive packets */
2810 if (callback)
2811 silc_packet_stream_link(pws->stream, &silc_packet_wrap_cbs, pws,
2812 100000, pws->type, -1);
2813 else
2814 silc_packet_stream_unlink(pws->stream, &silc_packet_wrap_cbs, pws);
2815
2816 pws->callback = callback;
2817 pws->context = context;
2818
2819 return TRUE;
2820 }
2821
2822 /* Return schedule */
2823
silc_packet_wrap_get_schedule(SilcStream stream)2824 SilcSchedule silc_packet_wrap_get_schedule(SilcStream stream)
2825 {
2826 SilcPacketWrapperStream pws = stream;
2827 return silc_stream_get_schedule(pws->stream->stream);
2828 }
2829
2830 /* Wraps packet stream into SilcStream. */
2831
silc_packet_stream_wrap(SilcPacketStream stream,SilcPacketType type,SilcPacketFlags flags,SilcBool blocking_mode,SilcIdType src_id_type,void * src_id,SilcIdType dst_id_type,void * dst_id,SilcPacketWrapCoder coder,void * context)2832 SilcStream silc_packet_stream_wrap(SilcPacketStream stream,
2833 SilcPacketType type,
2834 SilcPacketFlags flags,
2835 SilcBool blocking_mode,
2836 SilcIdType src_id_type, void *src_id,
2837 SilcIdType dst_id_type, void *dst_id,
2838 SilcPacketWrapCoder coder,
2839 void *context)
2840 {
2841 SilcPacketWrapperStream pws;
2842
2843 pws = silc_calloc(1, sizeof(*pws));
2844 if (!pws)
2845 return NULL;
2846
2847 SILC_LOG_DEBUG(("Wrapping packet stream %p to stream %p", stream, pws));
2848
2849 pws->ops = &silc_packet_stream_ops;
2850 pws->stream = stream;
2851 pws->type = type;
2852 pws->flags = flags;
2853 pws->blocking = blocking_mode;
2854 pws->coder = coder;
2855 pws->coder_context = context;
2856
2857 if (src_id) {
2858 pws->src_id = silc_id_dup(src_id, src_id_type);
2859 if (!pws->src_id) {
2860 silc_free(pws);
2861 return NULL;
2862 }
2863 pws->src_id_type = src_id_type;
2864 }
2865
2866 if (dst_id) {
2867 pws->dst_id = silc_id_dup(dst_id, dst_id_type);
2868 if (!pws->dst_id) {
2869 silc_free(pws);
2870 return NULL;
2871 }
2872 pws->dst_id_type = dst_id_type;
2873 }
2874
2875 /* Allocate small amount for encoder buffer. */
2876 if (pws->coder)
2877 pws->encbuf = silc_buffer_alloc(8);
2878
2879 if (pws->blocking) {
2880 /* Blocking mode. Use packet waiter to do the thing. */
2881 pws->waiter = silc_packet_wait_init(pws->stream, NULL, pws->type, -1);
2882 if (!pws->waiter) {
2883 silc_free(pws);
2884 return NULL;
2885 }
2886 } else {
2887 /* Non-blocking mode */
2888 silc_mutex_alloc(&pws->lock);
2889 silc_list_init(pws->in_queue, struct SilcPacketStruct, next);
2890 }
2891
2892 silc_packet_stream_ref(stream);
2893
2894 return (SilcStream)pws;
2895 }
2896
2897 const SilcStreamOps silc_packet_stream_ops =
2898 {
2899 silc_packet_wrap_read,
2900 silc_packet_wrap_write,
2901 silc_packet_wrap_close,
2902 silc_packet_wrap_destroy,
2903 silc_packet_wrap_notifier,
2904 silc_packet_wrap_get_schedule,
2905 };
2906