/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugins.d/mandosclient.c

  • Committer: Teddy Hogeborn
  • Date: 2008-07-22 06:23:29 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080722062329-jaex5y5mslf6sqjx
* mandos-clients.conf ([DEFAULT]): New section.

* plugins.d/mandosclient.c (start_mandos_communication): Only print if
                                                         debugging.
                                                         Print server
                                                         name.
                                                         Bug fix: Loop
                                                         until suc-
                                                         cess.

* server.py (serverName): Set via option, not globally.
  (Client.__init__): Removed argument "options".  Require "timeout"
                     and "interval" arguments.
  (tcp_handler.handle): Set "priority" from self.server.options.
  (main): Removed "--timeout" and "--interval" options.  New options
          "--priority" and "--servicename".  Add defaults for
          "timeout" and "interval".  Set "serviceName" from options.
          Do not pass "options" to "Client()".

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***
2
 
  This file is part of avahi.
3
 
 
4
 
  avahi is free software; you can redistribute it and/or modify it
5
 
  under the terms of the GNU Lesser General Public License as
6
 
  published by the Free Software Foundation; either version 2.1 of the
7
 
  License, or (at your option) any later version.
8
 
 
9
 
  avahi is distributed in the hope that it will be useful, but WITHOUT
10
 
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
 
  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12
 
  Public License for more details.
13
 
 
14
 
  You should have received a copy of the GNU Lesser General Public
15
 
  License along with avahi; if not, write to the Free Software
16
 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17
 
  USA.
18
 
***/
 
1
/*  -*- coding: utf-8 -*- */
 
2
/*
 
3
 * Mandos client - get and decrypt data from a Mandos server
 
4
 *
 
5
 * This program is partly derived from an example program for an Avahi
 
6
 * service browser, downloaded from
 
7
 * <http://avahi.org/browser/examples/core-browse-services.c>.  This
 
8
 * includes the following functions: "resolve_callback",
 
9
 * "browse_callback", and parts of "main".
 
10
 * 
 
11
 * Everything else is Copyright © 2007-2008 Teddy Hogeborn and Björn
 
12
 * Påhlsson.
 
13
 * 
 
14
 * This program is free software: you can redistribute it and/or
 
15
 * modify it under the terms of the GNU General Public License as
 
16
 * published by the Free Software Foundation, either version 3 of the
 
17
 * License, or (at your option) any later version.
 
18
 * 
 
19
 * This program is distributed in the hope that it will be useful, but
 
20
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
22
 * General Public License for more details.
 
23
 * 
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program.  If not, see
 
26
 * <http://www.gnu.org/licenses/>.
 
27
 * 
 
28
 * Contact the authors at <https://www.fukt.bsnet.se/~belorn/> and
 
29
 * <https://www.fukt.bsnet.se/~teddy/>.
 
30
 */
 
31
 
 
32
#define _FORTIFY_SOURCE 2
19
33
 
20
34
#define _LARGEFILE_SOURCE
21
35
#define _FILE_OFFSET_BITS 64
34
48
#include <avahi-common/error.h>
35
49
 
36
50
//mandos client part
37
 
#include <sys/types.h>          /* socket(), setsockopt(), inet_pton() */
38
 
#include <sys/socket.h>         /* socket(), setsockopt(), struct sockaddr_in6, struct in6_addr, inet_pton() */
39
 
#include <gnutls/gnutls.h>      /* ALL GNUTLS STUFF */
40
 
#include <gnutls/openpgp.h>     /* gnutls with openpgp stuff */
 
51
#include <sys/types.h>          /* socket(), inet_pton() */
 
52
#include <sys/socket.h>         /* socket(), struct sockaddr_in6,
 
53
                                   struct in6_addr, inet_pton() */
 
54
#include <gnutls/gnutls.h>      /* All GnuTLS stuff */
 
55
#include <gnutls/openpgp.h>     /* GnuTLS with openpgp stuff */
41
56
 
42
57
#include <unistd.h>             /* close() */
43
58
#include <netinet/in.h>
62
77
#define DH_BITS 1024
63
78
 
64
79
bool debug = false;
65
 
char *interface = "eth0";
66
80
 
67
81
typedef struct {
68
82
  gnutls_session_t session;
71
85
} encrypted_session;
72
86
 
73
87
 
74
 
ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
 
88
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
 
89
                            char **new_packet, const char *homedir){
75
90
  gpgme_data_t dh_crypto, dh_plain;
76
91
  gpgme_ctx_t ctx;
77
92
  gpgme_error_t rc;
78
93
  ssize_t ret;
79
 
  size_t new_packet_capacity = 0;
80
 
  size_t new_packet_length = 0;
 
94
  ssize_t new_packet_capacity = 0;
 
95
  ssize_t new_packet_length = 0;
81
96
  gpgme_engine_info_t engine_info;
82
97
 
83
98
  if (debug){
84
 
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
 
99
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
85
100
  }
86
101
  
87
102
  /* Init GPGME */
132
147
    return -1;
133
148
  }
134
149
  
135
 
  /* Decrypt data from the FILE pointer to the plaintext data buffer */
 
150
  /* Decrypt data from the FILE pointer to the plaintext data
 
151
     buffer */
136
152
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
137
153
  if (rc != GPG_ERR_NO_ERROR){
138
154
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
141
157
  }
142
158
 
143
159
  if(debug){
144
 
    fprintf(stderr, "decryption of gpg packet succeeded\n");
 
160
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
145
161
  }
146
162
 
147
163
  if (debug){
150
166
    if (result == NULL){
151
167
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
152
168
    } else {
153
 
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
154
 
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
 
169
      fprintf(stderr, "Unsupported algorithm: %s\n",
 
170
              result->unsupported_algorithm);
 
171
      fprintf(stderr, "Wrong key usage: %d\n",
 
172
              result->wrong_key_usage);
155
173
      if(result->file_name != NULL){
156
174
        fprintf(stderr, "File name: %s\n", result->file_name);
157
175
      }
163
181
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
164
182
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
165
183
          fprintf(stderr, "Secret key available: %s\n",
166
 
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
 
184
                  recipient->status == GPG_ERR_NO_SECKEY
 
185
                  ? "No" : "Yes");
167
186
          recipient = recipient->next;
168
187
        }
169
188
      }
174
193
  gpgme_data_release(dh_crypto);
175
194
  
176
195
  /* Seek back to the beginning of the GPGME plaintext data buffer */
177
 
  gpgme_data_seek(dh_plain, 0, SEEK_SET);
 
196
  gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
178
197
 
179
198
  *new_packet = 0;
180
199
  while(true){
181
200
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
182
 
      *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
 
201
      *new_packet = realloc(*new_packet,
 
202
                            (unsigned int)new_packet_capacity
 
203
                            + BUFFER_SIZE);
183
204
      if (*new_packet == NULL){
184
205
        perror("realloc");
185
206
        return -1;
187
208
      new_packet_capacity += BUFFER_SIZE;
188
209
    }
189
210
    
190
 
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
 
211
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
 
212
                          BUFFER_SIZE);
191
213
    /* Print the data, if any */
192
214
    if (ret == 0){
193
 
      /* If password is empty, then a incorrect error will be printed */
194
215
      break;
195
216
    }
196
217
    if(ret < 0){
220
241
  return ret;
221
242
}
222
243
 
223
 
void debuggnutls(int level, const char* string){
 
244
void debuggnutls(__attribute__((unused)) int level,
 
245
                 const char* string){
224
246
  fprintf(stderr, "%s", string);
225
247
}
226
248
 
227
249
int initgnutls(encrypted_session *es){
228
250
  const char *err;
229
251
  int ret;
230
 
 
 
252
  
231
253
  if(debug){
232
 
    fprintf(stderr, "Initializing gnutls\n");
 
254
    fprintf(stderr, "Initializing GnuTLS\n");
233
255
  }
234
 
 
235
256
  
236
257
  if ((ret = gnutls_global_init ())
237
258
      != GNUTLS_E_SUCCESS) {
244
265
    gnutls_global_set_log_function(debuggnutls);
245
266
  }
246
267
  
247
 
 
248
268
  /* openpgp credentials */
249
269
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
250
270
      != GNUTLS_E_SUCCESS) {
251
 
    fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
 
271
    fprintf (stderr, "memory error: %s\n",
 
272
             safer_gnutls_strerror(ret));
252
273
    return -1;
253
274
  }
254
 
 
 
275
  
255
276
  if(debug){
256
 
    fprintf(stderr, "Attempting to use openpgp certificate %s"
257
 
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
 
277
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
 
278
            " and keyfile %s as GnuTLS credentials\n", CERTFILE,
 
279
            KEYFILE);
258
280
  }
259
 
 
 
281
  
260
282
  ret = gnutls_certificate_set_openpgp_key_file
261
283
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
262
284
  if (ret != GNUTLS_E_SUCCESS) {
263
285
    fprintf
264
 
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
 
286
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
 
287
       " '%s')\n",
265
288
       ret, CERTFILE, KEYFILE);
266
289
    fprintf(stdout, "The Error is: %s\n",
267
290
            safer_gnutls_strerror(ret));
268
291
    return -1;
269
292
  }
270
 
 
271
 
  //Gnutls server initialization
 
293
  
 
294
  //GnuTLS server initialization
272
295
  if ((ret = gnutls_dh_params_init (&es->dh_params))
273
296
      != GNUTLS_E_SUCCESS) {
274
297
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
275
298
             safer_gnutls_strerror(ret));
276
299
    return -1;
277
300
  }
278
 
 
 
301
  
279
302
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
280
303
      != GNUTLS_E_SUCCESS) {
281
304
    fprintf (stderr, "Error in prime generation: %s\n",
282
305
             safer_gnutls_strerror(ret));
283
306
    return -1;
284
307
  }
285
 
 
 
308
  
286
309
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
287
 
 
288
 
  // Gnutls session creation
 
310
  
 
311
  // GnuTLS session creation
289
312
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
290
313
      != GNUTLS_E_SUCCESS){
291
 
    fprintf(stderr, "Error in gnutls session initialization: %s\n",
 
314
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
292
315
            safer_gnutls_strerror(ret));
293
316
  }
294
 
 
 
317
  
295
318
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
296
319
      != GNUTLS_E_SUCCESS) {
297
320
    fprintf(stderr, "Syntax error at: %s\n", err);
298
 
    fprintf(stderr, "Gnutls error: %s\n",
 
321
    fprintf(stderr, "GnuTLS error: %s\n",
299
322
            safer_gnutls_strerror(ret));
300
323
    return -1;
301
324
  }
302
 
 
 
325
  
303
326
  if ((ret = gnutls_credentials_set
304
327
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
305
328
      != GNUTLS_E_SUCCESS) {
307
330
            safer_gnutls_strerror(ret));
308
331
    return -1;
309
332
  }
310
 
 
 
333
  
311
334
  /* ignore client certificate if any. */
312
 
  gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
 
335
  gnutls_certificate_server_set_request (es->session,
 
336
                                         GNUTLS_CERT_IGNORE);
313
337
  
314
338
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
315
339
  
316
340
  return 0;
317
341
}
318
342
 
319
 
void empty_log(AvahiLogLevel level, const char *txt){}
 
343
void empty_log(__attribute__((unused)) AvahiLogLevel level,
 
344
               __attribute__((unused)) const char *txt){}
320
345
 
321
 
int start_mandos_communication(char *ip, uint16_t port){
 
346
int start_mandos_communication(const char *ip, uint16_t port,
 
347
                               unsigned int if_index){
322
348
  int ret, tcp_sd;
323
349
  struct sockaddr_in6 to;
324
350
  encrypted_session es;
327
353
  size_t buffer_length = 0;
328
354
  size_t buffer_capacity = 0;
329
355
  ssize_t decrypted_buffer_size;
 
356
  size_t written = 0;
330
357
  int retval = 0;
331
 
 
 
358
  char interface[IF_NAMESIZE];
 
359
  
332
360
  if(debug){
333
361
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
334
362
  }
338
366
    perror("socket");
339
367
    return -1;
340
368
  }
341
 
 
 
369
  
 
370
  if(if_indextoname(if_index, interface) == NULL){
 
371
    if(debug){
 
372
      perror("if_indextoname");
 
373
    }
 
374
    return -1;
 
375
  }
 
376
  
342
377
  if(debug){
343
378
    fprintf(stderr, "Binding to interface %s\n", interface);
344
379
  }
345
 
 
346
 
  ret = setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, interface, 5);
347
 
  if(tcp_sd < 0) {
348
 
    perror("setsockopt bindtodevice");
349
 
    return -1;
350
 
  }
351
380
  
352
 
  memset(&to,0,sizeof(to));
 
381
  memset(&to,0,sizeof(to));     /* Spurious warning */
353
382
  to.sin6_family = AF_INET6;
354
383
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
355
384
  if (ret < 0 ){
360
389
    fprintf(stderr, "Bad address: %s\n", ip);
361
390
    return -1;
362
391
  }
363
 
  to.sin6_port = htons(port);
364
 
  to.sin6_scope_id = if_nametoindex(interface);
365
 
 
 
392
  to.sin6_port = htons(port);   /* Spurious warning */
 
393
  
 
394
  to.sin6_scope_id = (uint32_t)if_index;
 
395
  
366
396
  if(debug){
367
397
    fprintf(stderr, "Connection to: %s\n", ip);
368
398
  }
378
408
    retval = -1;
379
409
    return -1;
380
410
  }
381
 
    
382
 
  
383
 
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
384
 
 
 
411
  
 
412
  gnutls_transport_set_ptr (es.session,
 
413
                            (gnutls_transport_ptr_t) tcp_sd);
 
414
  
385
415
  if(debug){
386
 
    fprintf(stderr, "Establishing tls session with %s\n", ip);
 
416
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
387
417
  }
388
 
 
389
418
  
390
419
  ret = gnutls_handshake (es.session);
391
420
  
392
421
  if (ret != GNUTLS_E_SUCCESS){
393
 
    fprintf(stderr, "\n*** Handshake failed ***\n");
394
 
    gnutls_perror (ret);
 
422
    if(debug){
 
423
      fprintf(stderr, "\n*** Handshake failed ***\n");
 
424
      gnutls_perror (ret);
 
425
    }
395
426
    retval = -1;
396
427
    goto exit;
397
428
  }
398
 
 
399
 
  //Retrieve gpg packet that contains the wanted password
400
 
 
 
429
  
 
430
  //Retrieve OpenPGP packet that contains the wanted password
 
431
  
401
432
  if(debug){
402
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
 
433
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
 
434
            ip);
403
435
  }
404
436
 
405
437
  while(true){
432
464
        }
433
465
        break;
434
466
      default:
435
 
        fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
 
467
        fprintf(stderr, "Unknown error while reading data from"
 
468
                " encrypted session with mandos server\n");
436
469
        retval = -1;
437
470
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
438
471
        goto exit;
439
472
      }
440
473
    } else {
441
 
      buffer_length += ret;
 
474
      buffer_length += (size_t) ret;
442
475
    }
443
476
  }
444
477
  
445
478
  if (buffer_length > 0){
446
 
    if ((decrypted_buffer_size = gpg_packet_decrypt(buffer, buffer_length, &decrypted_buffer, CERT_ROOT)) >= 0){
447
 
      fwrite (decrypted_buffer, 1, decrypted_buffer_size, stdout);
 
479
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
 
480
                                               buffer_length,
 
481
                                               &decrypted_buffer,
 
482
                                               CERT_ROOT);
 
483
    if (decrypted_buffer_size >= 0){
 
484
      while(written < decrypted_buffer_size){
 
485
        ret = (int)fwrite (decrypted_buffer + written, 1,
 
486
                           (size_t)decrypted_buffer_size - written,
 
487
                           stdout);
 
488
        if(ret == 0 and ferror(stdout)){
 
489
          if(debug){
 
490
            fprintf(stderr, "Error writing encrypted data: %s\n",
 
491
                    strerror(errno));
 
492
          }
 
493
          retval = -1;
 
494
          break;
 
495
        }
 
496
        written += (size_t)ret;
 
497
      }
448
498
      free(decrypted_buffer);
449
499
    } else {
450
500
      retval = -1;
454
504
  //shutdown procedure
455
505
 
456
506
  if(debug){
457
 
    fprintf(stderr, "Closing tls session\n");
 
507
    fprintf(stderr, "Closing TLS session\n");
458
508
  }
459
509
 
460
510
  free(buffer);
472
522
 
473
523
static void resolve_callback(
474
524
    AvahiSServiceResolver *r,
475
 
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
 
525
    AvahiIfIndex interface,
476
526
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
477
527
    AvahiResolverEvent event,
478
528
    const char *name,
481
531
    const char *host_name,
482
532
    const AvahiAddress *address,
483
533
    uint16_t port,
484
 
    AvahiStringList *txt,
485
 
    AvahiLookupResultFlags flags,
 
534
    AVAHI_GCC_UNUSED AvahiStringList *txt,
 
535
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
486
536
    AVAHI_GCC_UNUSED void* userdata) {
487
537
    
488
 
    assert(r);
489
 
 
490
 
    /* Called whenever a service has been resolved successfully or timed out */
491
 
 
492
 
    switch (event) {
493
 
        case AVAHI_RESOLVER_FAILURE:
494
 
            fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_server_errno(server)));
495
 
            break;
496
 
 
497
 
        case AVAHI_RESOLVER_FOUND: {
498
 
          char ip[AVAHI_ADDRESS_STR_MAX];
499
 
            avahi_address_snprint(ip, sizeof(ip), address);
500
 
            if(debug){
501
 
              fprintf(stderr, "Mandos server found at %s on port %d\n", ip, port);
502
 
            }
503
 
            int ret = start_mandos_communication(ip, port);
504
 
            if (ret == 0){
505
 
              exit(EXIT_SUCCESS);
506
 
            } else {
507
 
              exit(EXIT_FAILURE);
508
 
            }
509
 
        }
 
538
  assert(r);                    /* Spurious warning */
 
539
  
 
540
  /* Called whenever a service has been resolved successfully or
 
541
     timed out */
 
542
  
 
543
  switch (event) {
 
544
  default:
 
545
  case AVAHI_RESOLVER_FAILURE:
 
546
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
 
547
            " type '%s' in domain '%s': %s\n", name, type, domain,
 
548
            avahi_strerror(avahi_server_errno(server)));
 
549
    break;
 
550
    
 
551
  case AVAHI_RESOLVER_FOUND:
 
552
    {
 
553
      char ip[AVAHI_ADDRESS_STR_MAX];
 
554
      avahi_address_snprint(ip, sizeof(ip), address);
 
555
      if(debug){
 
556
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
 
557
                " port %d\n", name, host_name, ip, port);
 
558
      }
 
559
      int ret = start_mandos_communication(ip, port,
 
560
                                           (unsigned int) interface);
 
561
      if (ret == 0){
 
562
        exit(EXIT_SUCCESS);
 
563
      }
510
564
    }
511
 
    avahi_s_service_resolver_free(r);
 
565
  }
 
566
  avahi_s_service_resolver_free(r);
512
567
}
513
568
 
514
569
static void browse_callback(
523
578
    void* userdata) {
524
579
    
525
580
    AvahiServer *s = userdata;
526
 
    assert(b);
527
 
 
528
 
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
529
 
 
 
581
    assert(b);                  /* Spurious warning */
 
582
    
 
583
    /* Called whenever a new services becomes available on the LAN or
 
584
       is removed from the LAN */
 
585
    
530
586
    switch (event) {
531
 
 
532
 
        case AVAHI_BROWSER_FAILURE:
533
 
            
534
 
            fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_server_errno(server)));
535
 
            avahi_simple_poll_quit(simple_poll);
536
 
            return;
537
 
 
538
 
        case AVAHI_BROWSER_NEW:
539
 
            /* We ignore the returned resolver object. In the callback
540
 
               function we free it. If the server is terminated before
541
 
               the callback function is called the server will free
542
 
               the resolver for us. */
543
 
            
544
 
            if (!(avahi_s_service_resolver_new(s, interface, protocol, name, type, domain, AVAHI_PROTO_INET6, 0, resolve_callback, s)))
545
 
                fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_server_errno(s)));
546
 
            
547
 
            break;
548
 
 
549
 
        case AVAHI_BROWSER_REMOVE:
550
 
            break;
551
 
 
552
 
        case AVAHI_BROWSER_ALL_FOR_NOW:
553
 
        case AVAHI_BROWSER_CACHE_EXHAUSTED:
554
 
            break;
 
587
    default:
 
588
    case AVAHI_BROWSER_FAILURE:
 
589
      
 
590
      fprintf(stderr, "(Browser) %s\n",
 
591
              avahi_strerror(avahi_server_errno(server)));
 
592
      avahi_simple_poll_quit(simple_poll);
 
593
      return;
 
594
      
 
595
    case AVAHI_BROWSER_NEW:
 
596
      /* We ignore the returned resolver object. In the callback
 
597
         function we free it. If the server is terminated before
 
598
         the callback function is called the server will free
 
599
         the resolver for us. */
 
600
      
 
601
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
 
602
                                         type, domain,
 
603
                                         AVAHI_PROTO_INET6, 0,
 
604
                                         resolve_callback, s)))
 
605
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
 
606
                avahi_strerror(avahi_server_errno(s)));
 
607
      break;
 
608
      
 
609
    case AVAHI_BROWSER_REMOVE:
 
610
      break;
 
611
      
 
612
    case AVAHI_BROWSER_ALL_FOR_NOW:
 
613
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
614
      break;
555
615
    }
556
616
}
557
617
 
561
621
    int error;
562
622
    int ret;
563
623
    int returncode = EXIT_SUCCESS;
564
 
 
 
624
    const char *interface = "eth0";
 
625
    
565
626
    while (true){
566
627
      static struct option long_options[] = {
567
628
        {"debug", no_argument, (int *)&debug, 1},
568
629
        {"interface", required_argument, 0, 'i'},
569
630
        {0, 0, 0, 0} };
570
 
 
 
631
      
571
632
      int option_index = 0;
572
 
      ret = getopt_long (argc, argv, "i:", long_options, &option_index);
573
 
 
 
633
      ret = getopt_long (argc, argv, "i:", long_options,
 
634
                         &option_index);
 
635
      
574
636
      if (ret == -1){
575
637
        break;
576
638
      }
591
653
    }
592
654
    
593
655
    /* Initialize the psuedo-RNG */
594
 
    srand(time(NULL));
 
656
    srand((unsigned int) time(NULL));
595
657
 
596
658
    /* Allocate main loop object */
597
659
    if (!(simple_poll = avahi_simple_poll_new())) {
608
670
    config.publish_domain = 0;
609
671
 
610
672
    /* Allocate a new server */
611
 
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
 
673
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
 
674
                              &config, NULL, NULL, &error);
612
675
 
613
676
    /* Free the configuration data */
614
677
    avahi_server_config_free(&config);
615
678
 
616
679
    /* Check if creating the server object succeeded */
617
680
    if (!server) {
618
 
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
 
681
        fprintf(stderr, "Failed to create server: %s\n",
 
682
                avahi_strerror(error));
619
683
        returncode = EXIT_FAILURE;
620
684
        goto exit;
621
685
    }
622
686
    
623
687
    /* Create the service browser */
624
 
    if (!(sb = avahi_s_service_browser_new(server, if_nametoindex("eth0"), AVAHI_PROTO_INET6, "_mandos._tcp", NULL, 0, browse_callback, server))) {
625
 
        fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_server_errno(server)));
 
688
    sb = avahi_s_service_browser_new(server,
 
689
                                     (AvahiIfIndex)
 
690
                                     if_nametoindex(interface),
 
691
                                     AVAHI_PROTO_INET6,
 
692
                                     "_mandos._tcp", NULL, 0,
 
693
                                     browse_callback, server);
 
694
    if (!sb) {
 
695
        fprintf(stderr, "Failed to create service browser: %s\n",
 
696
                avahi_strerror(avahi_server_errno(server)));
626
697
        returncode = EXIT_FAILURE;
627
698
        goto exit;
628
699
    }
635
706
    
636
707
    avahi_simple_poll_loop(simple_poll);
637
708
    
638
 
exit:
 
709
 exit:
639
710
 
640
711
    if (debug){
641
712
      fprintf(stderr, "%s exiting\n", argv[0]);