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