Added checking for maximum packet length.
[silc.git] / lib / silcclient / client_channel.c
1 /*
2
3   client_channel.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21 /* This file includes channel message sending and receiving routines,
22    channel key receiving and setting, and channel private key handling 
23    routines. */
24
25 #include "silcincludes.h"
26 #include "silcclient.h"
27 #include "client_internal.h"
28
29 /* Sends packet to the `channel'. Packet to channel is always encrypted
30    differently from "normal" packets. SILC header of the packet is 
31    encrypted with the next receiver's key and the rest of the packet is
32    encrypted with the channel specific key. Padding and HMAC is computed
33    with the next receiver's key. The `data' is the channel message. If
34    the `force_send' is TRUE then the packet is sent immediately. */
35
36 void silc_client_send_channel_message(SilcClient client, 
37                                       SilcClientConnection conn,
38                                       SilcChannelEntry channel,
39                                       SilcChannelPrivateKey key,
40                                       SilcMessageFlags flags,
41                                       unsigned char *data, 
42                                       SilcUInt32 data_len, 
43                                       int force_send)
44 {
45   int i;
46   SilcSocketConnection sock = conn->sock;
47   SilcBuffer payload;
48   SilcPacketContext packetdata;
49   SilcCipher cipher;
50   SilcHmac hmac;
51   unsigned char *id_string;
52   SilcUInt32 iv_len;
53   int block_len;
54
55   SILC_LOG_DEBUG(("Sending packet to channel"));
56
57   /* Take the key to be used */
58   if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
59     if (key) {
60       /* Use key application specified */
61       cipher = key->cipher;
62       hmac = key->hmac;
63     } else if (channel->curr_key) {
64       /* Use current private key */
65       cipher = channel->curr_key->cipher;
66       hmac = channel->curr_key->hmac;
67     } else if (!channel->curr_key && channel->private_keys) {
68       /* Use just some private key since we don't know what to use 
69          and private keys are set. */
70       silc_dlist_start(channel->private_keys);
71       key = silc_dlist_get(channel->private_keys);
72       cipher = key->cipher;
73       hmac = key->hmac;
74       
75       /* Use this key as current private key */
76       channel->curr_key = key;
77     } else {
78       /* Use normal channel key generated by the server */
79       cipher = channel->channel_key;
80       hmac = channel->hmac;
81     }
82   } else {
83     /* Use normal channel key generated by the server */
84     cipher = channel->channel_key;
85     hmac = channel->hmac;
86   }
87
88   if (!cipher || !hmac)
89     return;
90
91   block_len = silc_cipher_get_block_len(cipher);
92
93   /* Generate IV */
94   iv_len = silc_cipher_get_block_len(cipher);
95   if (channel->iv[0] == '\0')
96     for (i = 0; i < iv_len; i++) channel->iv[i] = 
97                                    silc_rng_get_byte(client->rng);
98   else
99     silc_hash_make(client->internal->md5hash, channel->iv, iv_len, 
100                    channel->iv);
101
102   /* Encode the channel payload. This also encrypts the message payload. */
103   payload = silc_channel_message_payload_encode(flags, data_len, data, iv_len, 
104                                                 channel->iv, cipher, hmac,
105                                                 client->rng);
106
107   /* Get data used in packet header encryption, keys and stuff. */
108   cipher = conn->send_key;
109   hmac = conn->hmac_send;
110   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
111
112   /* Set the packet context pointers. The destination ID is always
113      the Channel ID of the channel. Server and router will handle the
114      distribution of the packet. */
115   data = payload->data;
116   data_len = payload->len;
117   packetdata.flags = 0;
118   packetdata.type = SILC_PACKET_CHANNEL_MESSAGE;
119   packetdata.src_id = conn->local_id_data;
120   packetdata.src_id_len = silc_id_get_len(conn->local_id, SILC_ID_CLIENT);
121   packetdata.src_id_type = SILC_ID_CLIENT;
122   packetdata.dst_id = id_string;
123   packetdata.dst_id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
124   packetdata.dst_id_type = SILC_ID_CHANNEL;
125   data_len = SILC_PACKET_DATALEN(data_len, SILC_PACKET_HEADER_LEN +
126                                  packetdata.src_id_len +
127                                  packetdata.dst_id_len);
128   packetdata.truelen = data_len + SILC_PACKET_HEADER_LEN + 
129     packetdata.src_id_len + packetdata.dst_id_len;
130   packetdata.padlen = SILC_PACKET_PADLEN((SILC_PACKET_HEADER_LEN +
131                                           packetdata.src_id_len +
132                                           packetdata.dst_id_len), block_len);
133
134   /* Prepare outgoing data buffer for packet sending */
135   silc_packet_send_prepare(sock, 
136                            SILC_PACKET_HEADER_LEN +
137                            packetdata.src_id_len + 
138                            packetdata.dst_id_len,
139                            packetdata.padlen,
140                            data_len);
141
142   packetdata.buffer = sock->outbuf;
143
144   /* Put the channel message payload to the outgoing data buffer */
145   silc_buffer_put(sock->outbuf, data, data_len);
146
147   /* Create the outgoing packet */
148   silc_packet_assemble(&packetdata, cipher);
149
150   /* Encrypt the header and padding of the packet. This is encrypted 
151      with normal session key shared with our server. */
152   silc_packet_encrypt(cipher, hmac, conn->psn_send++,
153                       sock->outbuf, SILC_PACKET_HEADER_LEN + 
154                       packetdata.src_id_len + packetdata.dst_id_len +
155                       packetdata.padlen);
156
157   SILC_LOG_HEXDUMP(("Packet to channel, len %d", sock->outbuf->len),
158                    sock->outbuf->data, sock->outbuf->len);
159
160   /* Now actually send the packet */
161   silc_client_packet_send_real(client, sock, force_send);
162   silc_buffer_free(payload);
163   silc_free(id_string);
164 }
165
166 typedef struct {
167   SilcChannelMessagePayload payload;
168   SilcChannelID *channel_id;
169 } *SilcChannelClientResolve;
170
171 static void silc_client_channel_message_cb(SilcClient client,
172                                            SilcClientConnection conn,
173                                            SilcClientEntry *clients,
174                                            SilcUInt32 clients_count,
175                                            void *context)
176 {
177   SilcChannelClientResolve res = (SilcChannelClientResolve)context;
178
179   if (clients_count == 1) {
180     SilcChannelEntry channel;
181     unsigned char *message;
182
183     channel = silc_client_get_channel_by_id(client, conn, res->channel_id);
184     if (!channel)
185       goto out;
186
187     /* If this client is not on channel, add it there since it clearly
188        is there. */
189     if (!silc_client_on_channel(channel, clients[0])) {
190       SilcChannelUser chu = silc_calloc(1, sizeof(*chu));
191       chu->client = clients[0];
192       chu->channel = channel;
193       silc_hash_table_add(channel->user_list, clients[0], chu);
194       silc_hash_table_add(clients[0]->channels, channel, chu);
195     }
196
197     message = silc_channel_message_get_data(res->payload, NULL);
198     
199     /* Pass the message to application */
200     client->internal->ops->channel_message(
201                                client, conn, clients[0], channel,
202                                silc_channel_message_get_flags(res->payload),
203                                message);
204   }
205
206  out:
207   silc_channel_message_payload_free(res->payload);
208   silc_free(res->channel_id);
209   silc_free(res);
210 }
211
212 /* Process received message to a channel (or from a channel, really). This
213    decrypts the channel message with channel specific key and parses the
214    channel payload. Finally it displays the message on the screen. */
215
216 void silc_client_channel_message(SilcClient client, 
217                                  SilcSocketConnection sock, 
218                                  SilcPacketContext *packet)
219 {
220   SilcClientConnection conn = (SilcClientConnection)sock->user_data;
221   SilcBuffer buffer = packet->buffer;
222   SilcChannelMessagePayload payload = NULL;
223   SilcChannelID *id = NULL;
224   SilcChannelEntry channel;
225   SilcClientEntry client_entry;
226   SilcClientID *client_id = NULL;
227   unsigned char *message;
228
229   SILC_LOG_DEBUG(("Start"));
230
231   /* Sanity checks */
232   if (packet->dst_id_type != SILC_ID_CHANNEL)
233     goto out;
234
235   client_id = silc_id_str2id(packet->src_id, packet->src_id_len,
236                              SILC_ID_CLIENT);
237   if (!client_id)
238     goto out;
239   id = silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL);
240   if (!id)
241     goto out;
242
243   /* Find the channel entry from channels on this connection */
244   channel = silc_client_get_channel_by_id(client, conn, id);
245   if (!channel)
246     goto out;
247
248   /* If there is no channel private key then just decrypt the message 
249      with the channel key. If private keys are set then just go through
250      all private keys and check what decrypts correctly. */
251   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
252     /* Parse the channel message payload. This also decrypts the payload */
253     payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
254                                                  channel->channel_key,
255                                                  channel->hmac);
256
257     /* If decryption failed and we have just performed channel key rekey
258        we will use the old key in decryption. If that fails too then we
259        cannot do more and will drop the packet. */
260     if (!payload) {
261       if (!channel->old_channel_key) {
262         goto out;
263       }
264
265       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
266                                                    channel->old_channel_key,
267                                                    channel->old_hmac);
268       if (!payload) {
269         goto out;
270       }
271     }
272   } else if (channel->private_keys) {
273     SilcChannelPrivateKey entry;
274
275     silc_dlist_start(channel->private_keys);
276     while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
277       /* Parse the channel message payload. This also decrypts the payload */
278       payload = silc_channel_message_payload_parse(buffer->data, buffer->len, 
279                                                    entry->cipher,
280                                                    entry->hmac);
281       if (payload)
282         break;
283     }
284     if (entry == SILC_LIST_END)
285       goto out;
286   } else {
287     goto out;
288   }
289
290   /* Find client entry */
291   client_entry = silc_client_get_client_by_id(client, conn, client_id);
292   if (!client_entry || !client_entry->nickname) {
293     /* Resolve the client info */
294     SilcChannelClientResolve res = silc_calloc(1, sizeof(*res));
295     res->payload = payload;
296     res->channel_id = id;
297     silc_client_get_client_by_id_resolve(client, conn, client_id,
298                                          silc_client_channel_message_cb,
299                                          res);
300     payload = NULL;
301     id = NULL;
302     goto out;
303   }
304
305   if (!silc_client_on_channel(channel, client_entry)) {
306     SILC_LOG_WARNING(("Received channel message from client not on channel"));
307     goto out;
308   }
309
310   message = silc_channel_message_get_data(payload, NULL);
311
312   /* Pass the message to application */
313   client->internal->ops->channel_message(
314                                  client, conn, client_entry, channel,
315                                  silc_channel_message_get_flags(payload),
316                                  message);
317
318  out:
319   silc_free(id);
320   silc_free(client_id);
321   if (payload)
322     silc_channel_message_payload_free(payload);
323 }
324
325 /* Timeout callback that is called after a short period of time after the
326    new channel key has been created. This removes the old channel key all
327    together. */
328
329 SILC_TASK_CALLBACK(silc_client_save_channel_key_rekey)
330 {
331   SilcChannelEntry channel = (SilcChannelEntry)context;
332
333   if (channel->old_channel_key)
334     silc_cipher_free(channel->old_channel_key);
335   if (channel->old_hmac)
336     silc_hmac_free(channel->old_hmac);
337   channel->old_channel_key = NULL;
338   channel->old_hmac = NULL;
339   channel->rekey_task = NULL;
340 }
341
342 /* Saves channel key from encoded `key_payload'. This is used when we
343    receive Channel Key Payload and when we are processing JOIN command 
344    reply. */
345
346 void silc_client_save_channel_key(SilcClient client,
347                                   SilcClientConnection conn,
348                                   SilcBuffer key_payload, 
349                                   SilcChannelEntry channel)
350 {
351   unsigned char *id_string, *key, *cipher, *hmac, hash[32];
352   SilcUInt32 tmp_len;
353   SilcChannelID *id;
354   SilcChannelKeyPayload payload;
355
356   payload = silc_channel_key_payload_parse(key_payload->data,
357                                            key_payload->len);
358   if (!payload)
359     return;
360
361   id_string = silc_channel_key_get_id(payload, &tmp_len);
362   if (!id_string) {
363     silc_channel_key_payload_free(payload);
364     return;
365   }
366
367   id = silc_id_str2id(id_string, tmp_len, SILC_ID_CHANNEL);
368   if (!id) {
369     silc_channel_key_payload_free(payload);
370     return;
371   }
372
373   /* Find channel. */
374   if (!channel) {
375     channel = silc_client_get_channel_by_id(client, conn, id);
376     if (!channel)
377       goto out;
378   }
379
380   hmac = (channel->hmac ? (char *)silc_hmac_get_name(channel->hmac) : 
381           SILC_DEFAULT_HMAC);
382
383   /* Save the old key for a short period of time so that we can decrypt
384      channel message even after the rekey if some client would be sending
385      messages with the old key after the rekey. */
386   if (channel->old_channel_key)
387     silc_cipher_free(channel->old_channel_key);
388   if (channel->old_hmac)
389     silc_hmac_free(channel->old_hmac);
390   if (channel->rekey_task)
391     silc_schedule_task_del(client->schedule, channel->rekey_task);
392   channel->old_channel_key = channel->channel_key;
393   channel->old_hmac = channel->hmac;
394   channel->rekey_task = 
395     silc_schedule_task_add(client->schedule, 0,
396                            silc_client_save_channel_key_rekey, channel,
397                            10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
398
399   /* Free the old channel key data */
400   silc_free(channel->key);
401
402   /* Save the key */
403   key = silc_channel_key_get_key(payload, &tmp_len);
404   cipher = silc_channel_key_get_cipher(payload, NULL);
405   channel->key_len = tmp_len * 8;
406   channel->key = silc_memdup(key, tmp_len);
407
408   if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
409     client->internal->ops->say(
410                            conn->client, conn, 
411                            SILC_CLIENT_MESSAGE_AUDIT,
412                            "Cannot talk to channel: unsupported cipher %s", 
413                            cipher);
414     goto out;
415   }
416
417   /* Set the cipher key */
418   silc_cipher_set_key(channel->channel_key, key, channel->key_len);
419
420   /* Generate HMAC key from the channel key data and set it */
421   silc_hmac_alloc(hmac, NULL, &channel->hmac);
422   silc_hash_make(silc_hmac_get_hash(channel->hmac), key, tmp_len, hash);
423   silc_hmac_set_key(channel->hmac, hash, 
424                     silc_hash_len(silc_hmac_get_hash(channel->hmac)));
425   memset(hash, 0, sizeof(hash));
426
427  out:
428   silc_free(id);
429   silc_channel_key_payload_free(payload);
430 }
431
432 /* Processes received key for channel. The received key will be used
433    to protect the traffic on the channel for now on. Client must receive
434    the key to the channel before talking on the channel is possible. 
435    This is the key that server has generated, this is not the channel
436    private key, it is entirely local setting. */
437
438 void silc_client_receive_channel_key(SilcClient client,
439                                      SilcSocketConnection sock,
440                                      SilcBuffer packet)
441 {
442   SILC_LOG_DEBUG(("Received key for channel"));
443
444   /* Save the key */
445   silc_client_save_channel_key(client, sock->user_data, packet, NULL);
446 }
447
448 /* Adds private key for channel. This may be set only if the channel's mode
449    mask includes the SILC_CHANNEL_MODE_PRIVKEY. This returns FALSE if the
450    mode is not set. When channel has private key then the messages are
451    encrypted using that key. All clients on the channel must also know the
452    key in order to decrypt the messages. However, it is possible to have
453    several private keys per one channel. In this case only some of the
454    clients on the channel may know the one key and only some the other key.
455
456    If `cipher' and/or `hmac' is NULL then default values will be used 
457    (aes-256-cbc for cipher and hmac-sha1-96 for hmac).
458
459    The private key for channel is optional. If it is not set then the
460    channel messages are encrypted using the channel key generated by the
461    server. However, setting the private key (or keys) for the channel 
462    significantly adds security. If more than one key is set the library
463    will automatically try all keys at the message decryption phase. Note:
464    setting many keys slows down the decryption phase as all keys has to
465    be tried in order to find the correct decryption key. However, setting
466    a few keys does not have big impact to the decryption performace. 
467
468    NOTE: that this is entirely local setting. The key set using this function
469    is not sent to the network at any phase.
470
471    NOTE: If the key material was originated by the SKE protocol (using
472    silc_client_send_key_agreement) then the `key' MUST be the
473    key->send_enc_key as this is dictated by the SILC protocol. However,
474    currently it is not expected that the SKE key material would be used
475    as channel private key. However, this API allows it. */
476
477 int silc_client_add_channel_private_key(SilcClient client,
478                                         SilcClientConnection conn,
479                                         SilcChannelEntry channel,
480                                         char *cipher,
481                                         char *hmac,
482                                         unsigned char *key,
483                                         SilcUInt32 key_len)
484 {
485   SilcChannelPrivateKey entry;
486   unsigned char hash[32];
487   SilcSKEKeyMaterial *keymat;
488
489   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
490     return FALSE;
491
492   if (!cipher)
493     cipher = SILC_DEFAULT_CIPHER;
494   if (!hmac)
495     hmac = SILC_DEFAULT_HMAC;
496
497   if (!silc_cipher_is_supported(cipher))
498     return FALSE;
499
500   if (!silc_hmac_is_supported(hmac))
501     return FALSE;
502
503   /* Produce the key material */
504   keymat = silc_calloc(1, sizeof(*keymat));
505   if (silc_ske_process_key_material_data(key, key_len, 16, 256, 16, 
506                                          client->internal->md5hash, keymat) 
507       != SILC_SKE_STATUS_OK)
508     return FALSE;
509
510   /* Remove the current key, if it exists. */
511   if (channel->channel_key) {
512     silc_cipher_free(channel->channel_key);
513     memset(channel->key, 0, channel->key_len / 8);
514     silc_free(channel->key);
515     channel->channel_key = NULL;
516     channel->key = NULL;
517     channel->key_len = 0;
518   }
519   if (channel->hmac) {
520     silc_hmac_free(channel->hmac);
521     channel->hmac = NULL;
522   }
523
524   if (!channel->private_keys)
525     channel->private_keys = silc_dlist_init();
526
527   /* Save the key */
528   entry = silc_calloc(1, sizeof(*entry));
529   entry->key = silc_memdup(keymat->send_enc_key, keymat->enc_key_len / 8);
530   entry->key_len = keymat->enc_key_len / 8;
531
532   /* Allocate the cipher and set the key*/
533   silc_cipher_alloc(cipher, &entry->cipher);
534   silc_cipher_set_key(entry->cipher, entry->key, keymat->enc_key_len);
535
536   /* Generate HMAC key from the channel key data and set it */
537   silc_hmac_alloc(hmac, NULL, &entry->hmac);
538   silc_hash_make(silc_hmac_get_hash(entry->hmac), entry->key, 
539                  entry->key_len, hash);
540   silc_hmac_set_key(entry->hmac, hash, 
541                     silc_hash_len(silc_hmac_get_hash(entry->hmac)));
542   memset(hash, 0, sizeof(hash));
543
544   /* Add to the private keys list */
545   silc_dlist_add(channel->private_keys, entry);
546
547   if (!channel->curr_key)
548     channel->curr_key = entry;
549
550   /* Free the key material */
551   silc_ske_free_key_material(keymat);
552
553   return TRUE;
554 }
555
556 /* Removes all private keys from the `channel'. The old channel key is used
557    after calling this to protect the channel messages. Returns FALSE on
558    on error, TRUE otherwise. */
559
560 int silc_client_del_channel_private_keys(SilcClient client,
561                                          SilcClientConnection conn,
562                                          SilcChannelEntry channel)
563 {
564   SilcChannelPrivateKey entry;
565
566   if (!channel->private_keys)
567     return FALSE;
568
569   silc_dlist_start(channel->private_keys);
570   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
571     silc_dlist_del(channel->private_keys, entry);
572     memset(entry->key, 0, entry->key_len);
573     silc_free(entry->key);
574     silc_cipher_free(entry->cipher);
575     silc_hmac_free(entry->hmac);
576     silc_free(entry);
577   }
578
579   channel->curr_key = NULL;
580
581   silc_dlist_uninit(channel->private_keys);
582   channel->private_keys = NULL;
583
584   return TRUE;
585 }
586
587 /* Removes and frees private key `key' from the channel `channel'. The `key'
588    is retrieved by calling the function silc_client_list_channel_private_keys.
589    The key is not used after this. If the key was last private key then the
590    old channel key is used hereafter to protect the channel messages. This
591    returns FALSE on error, TRUE otherwise. */
592
593 int silc_client_del_channel_private_key(SilcClient client,
594                                         SilcClientConnection conn,
595                                         SilcChannelEntry channel,
596                                         SilcChannelPrivateKey key)
597 {
598   SilcChannelPrivateKey entry;
599
600   if (!channel->private_keys)
601     return FALSE;
602
603   silc_dlist_start(channel->private_keys);
604   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
605     if (entry == key) {
606       if (channel->curr_key == entry)
607         channel->curr_key = NULL;
608
609       silc_dlist_del(channel->private_keys, entry);
610       memset(entry->key, 0, entry->key_len);
611       silc_free(entry->key);
612       silc_cipher_free(entry->cipher);
613       silc_hmac_free(entry->hmac);
614       silc_free(entry);
615
616       if (silc_dlist_count(channel->private_keys) == 0) {
617         silc_dlist_uninit(channel->private_keys);
618         channel->private_keys = NULL;
619       }
620
621       return TRUE;
622     }
623   }
624
625   return FALSE;
626 }
627
628 /* Returns array (pointers) of private keys associated to the `channel'.
629    The caller must free the array by calling the function
630    silc_client_free_channel_private_keys. The pointers in the array may be
631    used to delete the specific key by giving the pointer as argument to the
632    function silc_client_del_channel_private_key. */
633
634 SilcChannelPrivateKey *
635 silc_client_list_channel_private_keys(SilcClient client,
636                                       SilcClientConnection conn,
637                                       SilcChannelEntry channel,
638                                       SilcUInt32 *key_count)
639 {
640   SilcChannelPrivateKey *keys = NULL, entry;
641   SilcUInt32 count = 0;
642
643   if (!channel->private_keys)
644     return NULL;
645
646   silc_dlist_start(channel->private_keys);
647   while ((entry = silc_dlist_get(channel->private_keys)) != SILC_LIST_END) {
648     keys = silc_realloc(keys, sizeof(*keys) * (count + 1));
649     keys[count] = entry;
650     count++;
651   }
652
653   if (key_count)
654     *key_count = count;
655
656   return keys;
657 }
658
659 /* Frees the SilcChannelPrivateKey array. */
660
661 void silc_client_free_channel_private_keys(SilcChannelPrivateKey *keys,
662                                            SilcUInt32 key_count)
663 {
664   silc_free(keys);
665 }
666
667 /* Returns the SilcChannelUser entry if the `client_entry' is joined on the 
668    channel indicated by the `channel'. NULL if client is not joined on
669    the channel. */
670
671 SilcChannelUser silc_client_on_channel(SilcChannelEntry channel,
672                                        SilcClientEntry client_entry)
673 {
674   SilcChannelUser chu;
675
676   if (silc_hash_table_find(channel->user_list, client_entry, NULL, 
677                            (void *)&chu))
678     return chu;
679
680   return NULL;
681 }