/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: Björn Påhlsson
  • Date: 2008-07-21 19:15:06 UTC
  • mfrom: (19 mandos)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: belorn@braxen-20080721191506-f4av11wlu2cmmeid
merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
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
***/
33
19
 
34
20
#define _LARGEFILE_SOURCE
35
21
#define _FILE_OFFSET_BITS 64
48
34
#include <avahi-common/error.h>
49
35
 
50
36
//mandos client part
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 */
 
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 */
56
41
 
57
42
#include <unistd.h>             /* close() */
58
43
#include <netinet/in.h>
77
62
#define DH_BITS 1024
78
63
 
79
64
bool debug = false;
 
65
char *interface = "eth0";
80
66
 
81
67
typedef struct {
82
68
  gnutls_session_t session;
85
71
} encrypted_session;
86
72
 
87
73
 
88
 
ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
89
 
                            char **new_packet, const char *homedir){
 
74
ssize_t gpg_packet_decrypt (char *packet, size_t packet_size, char **new_packet, char *homedir){
90
75
  gpgme_data_t dh_crypto, dh_plain;
91
76
  gpgme_ctx_t ctx;
92
77
  gpgme_error_t rc;
93
78
  ssize_t ret;
94
 
  ssize_t new_packet_capacity = 0;
95
 
  ssize_t new_packet_length = 0;
 
79
  size_t new_packet_capacity = 0;
 
80
  size_t new_packet_length = 0;
96
81
  gpgme_engine_info_t engine_info;
97
82
 
98
83
  if (debug){
99
 
    fprintf(stderr, "Trying to decrypt OpenPGP packet\n");
 
84
    fprintf(stderr, "Attempting to decrypt password from gpg packet\n");
100
85
  }
101
86
  
102
87
  /* Init GPGME */
147
132
    return -1;
148
133
  }
149
134
  
150
 
  /* Decrypt data from the FILE pointer to the plaintext data
151
 
     buffer */
 
135
  /* Decrypt data from the FILE pointer to the plaintext data buffer */
152
136
  rc = gpgme_op_decrypt(ctx, dh_crypto, dh_plain);
153
137
  if (rc != GPG_ERR_NO_ERROR){
154
138
    fprintf(stderr, "bad gpgme_op_decrypt: %s: %s\n",
157
141
  }
158
142
 
159
143
  if(debug){
160
 
    fprintf(stderr, "Decryption of OpenPGP packet succeeded\n");
 
144
    fprintf(stderr, "decryption of gpg packet succeeded\n");
161
145
  }
162
146
 
163
147
  if (debug){
166
150
    if (result == NULL){
167
151
      fprintf(stderr, "gpgme_op_decrypt_result failed\n");
168
152
    } else {
169
 
      fprintf(stderr, "Unsupported algorithm: %s\n",
170
 
              result->unsupported_algorithm);
171
 
      fprintf(stderr, "Wrong key usage: %d\n",
172
 
              result->wrong_key_usage);
 
153
      fprintf(stderr, "Unsupported algorithm: %s\n", result->unsupported_algorithm);
 
154
      fprintf(stderr, "Wrong key usage: %d\n", result->wrong_key_usage);
173
155
      if(result->file_name != NULL){
174
156
        fprintf(stderr, "File name: %s\n", result->file_name);
175
157
      }
181
163
                  gpgme_pubkey_algo_name(recipient->pubkey_algo));
182
164
          fprintf(stderr, "Key ID: %s\n", recipient->keyid);
183
165
          fprintf(stderr, "Secret key available: %s\n",
184
 
                  recipient->status == GPG_ERR_NO_SECKEY
185
 
                  ? "No" : "Yes");
 
166
                  recipient->status == GPG_ERR_NO_SECKEY ? "No" : "Yes");
186
167
          recipient = recipient->next;
187
168
        }
188
169
      }
193
174
  gpgme_data_release(dh_crypto);
194
175
  
195
176
  /* Seek back to the beginning of the GPGME plaintext data buffer */
196
 
  gpgme_data_seek(dh_plain, (off_t) 0, SEEK_SET);
 
177
  gpgme_data_seek(dh_plain, 0, SEEK_SET);
197
178
 
198
179
  *new_packet = 0;
199
180
  while(true){
200
181
    if (new_packet_length + BUFFER_SIZE > new_packet_capacity){
201
 
      *new_packet = realloc(*new_packet,
202
 
                            (unsigned int)new_packet_capacity
203
 
                            + BUFFER_SIZE);
 
182
      *new_packet = realloc(*new_packet, new_packet_capacity + BUFFER_SIZE);
204
183
      if (*new_packet == NULL){
205
184
        perror("realloc");
206
185
        return -1;
208
187
      new_packet_capacity += BUFFER_SIZE;
209
188
    }
210
189
    
211
 
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length,
212
 
                          BUFFER_SIZE);
 
190
    ret = gpgme_data_read(dh_plain, *new_packet + new_packet_length, BUFFER_SIZE);
213
191
    /* Print the data, if any */
214
192
    if (ret == 0){
 
193
      /* If password is empty, then a incorrect error will be printed */
215
194
      break;
216
195
    }
217
196
    if(ret < 0){
241
220
  return ret;
242
221
}
243
222
 
244
 
void debuggnutls(__attribute__((unused)) int level,
245
 
                 const char* string){
 
223
void debuggnutls(int level, const char* string){
246
224
  fprintf(stderr, "%s", string);
247
225
}
248
226
 
249
227
int initgnutls(encrypted_session *es){
250
228
  const char *err;
251
229
  int ret;
252
 
  
 
230
 
253
231
  if(debug){
254
 
    fprintf(stderr, "Initializing GnuTLS\n");
 
232
    fprintf(stderr, "Initializing gnutls\n");
255
233
  }
 
234
 
256
235
  
257
236
  if ((ret = gnutls_global_init ())
258
237
      != GNUTLS_E_SUCCESS) {
265
244
    gnutls_global_set_log_function(debuggnutls);
266
245
  }
267
246
  
 
247
 
268
248
  /* openpgp credentials */
269
249
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
270
250
      != GNUTLS_E_SUCCESS) {
271
 
    fprintf (stderr, "memory error: %s\n",
272
 
             safer_gnutls_strerror(ret));
 
251
    fprintf (stderr, "memory error: %s\n", safer_gnutls_strerror(ret));
273
252
    return -1;
274
253
  }
275
 
  
 
254
 
276
255
  if(debug){
277
 
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
278
 
            " and keyfile %s as GnuTLS credentials\n", CERTFILE,
279
 
            KEYFILE);
 
256
    fprintf(stderr, "Attempting to use openpgp certificate %s"
 
257
            " and keyfile %s as gnutls credentials\n", CERTFILE, KEYFILE);
280
258
  }
281
 
  
 
259
 
282
260
  ret = gnutls_certificate_set_openpgp_key_file
283
261
    (es->cred, CERTFILE, KEYFILE, GNUTLS_OPENPGP_FMT_BASE64);
284
262
  if (ret != GNUTLS_E_SUCCESS) {
285
263
    fprintf
286
 
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
287
 
       " '%s')\n",
 
264
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
288
265
       ret, CERTFILE, KEYFILE);
289
266
    fprintf(stdout, "The Error is: %s\n",
290
267
            safer_gnutls_strerror(ret));
291
268
    return -1;
292
269
  }
293
 
  
294
 
  //GnuTLS server initialization
 
270
 
 
271
  //Gnutls server initialization
295
272
  if ((ret = gnutls_dh_params_init (&es->dh_params))
296
273
      != GNUTLS_E_SUCCESS) {
297
274
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
298
275
             safer_gnutls_strerror(ret));
299
276
    return -1;
300
277
  }
301
 
  
 
278
 
302
279
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
303
280
      != GNUTLS_E_SUCCESS) {
304
281
    fprintf (stderr, "Error in prime generation: %s\n",
305
282
             safer_gnutls_strerror(ret));
306
283
    return -1;
307
284
  }
308
 
  
 
285
 
309
286
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
310
 
  
311
 
  // GnuTLS session creation
 
287
 
 
288
  // Gnutls session creation
312
289
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
313
290
      != GNUTLS_E_SUCCESS){
314
 
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
 
291
    fprintf(stderr, "Error in gnutls session initialization: %s\n",
315
292
            safer_gnutls_strerror(ret));
316
293
  }
317
 
  
 
294
 
318
295
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
319
296
      != GNUTLS_E_SUCCESS) {
320
297
    fprintf(stderr, "Syntax error at: %s\n", err);
321
 
    fprintf(stderr, "GnuTLS error: %s\n",
 
298
    fprintf(stderr, "Gnutls error: %s\n",
322
299
            safer_gnutls_strerror(ret));
323
300
    return -1;
324
301
  }
325
 
  
 
302
 
326
303
  if ((ret = gnutls_credentials_set
327
304
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
328
305
      != GNUTLS_E_SUCCESS) {
330
307
            safer_gnutls_strerror(ret));
331
308
    return -1;
332
309
  }
333
 
  
 
310
 
334
311
  /* ignore client certificate if any. */
335
 
  gnutls_certificate_server_set_request (es->session,
336
 
                                         GNUTLS_CERT_IGNORE);
 
312
  gnutls_certificate_server_set_request (es->session, GNUTLS_CERT_IGNORE);
337
313
  
338
314
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
339
315
  
340
316
  return 0;
341
317
}
342
318
 
343
 
void empty_log(__attribute__((unused)) AvahiLogLevel level,
344
 
               __attribute__((unused)) const char *txt){}
 
319
void empty_log(AvahiLogLevel level, const char *txt){}
345
320
 
346
 
int start_mandos_communication(const char *ip, uint16_t port,
347
 
                               unsigned int if_index){
 
321
int start_mandos_communication(char *ip, uint16_t port){
348
322
  int ret, tcp_sd;
349
323
  struct sockaddr_in6 to;
350
324
  encrypted_session es;
353
327
  size_t buffer_length = 0;
354
328
  size_t buffer_capacity = 0;
355
329
  ssize_t decrypted_buffer_size;
356
 
  size_t written = 0;
357
330
  int retval = 0;
358
 
  char interface[IF_NAMESIZE];
359
 
  
 
331
 
360
332
  if(debug){
361
333
    fprintf(stderr, "Setting up a tcp connection to %s\n", ip);
362
334
  }
366
338
    perror("socket");
367
339
    return -1;
368
340
  }
369
 
  
370
 
  if(if_indextoname(if_index, interface) == NULL){
371
 
    if(debug){
372
 
      perror("if_indextoname");
373
 
    }
374
 
    return -1;
375
 
  }
376
 
  
 
341
 
377
342
  if(debug){
378
343
    fprintf(stderr, "Binding to interface %s\n", interface);
379
344
  }
 
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
  }
380
351
  
381
 
  memset(&to,0,sizeof(to));     /* Spurious warning */
 
352
  memset(&to,0,sizeof(to));
382
353
  to.sin6_family = AF_INET6;
383
354
  ret = inet_pton(AF_INET6, ip, &to.sin6_addr);
384
355
  if (ret < 0 ){
389
360
    fprintf(stderr, "Bad address: %s\n", ip);
390
361
    return -1;
391
362
  }
392
 
  to.sin6_port = htons(port);   /* Spurious warning */
393
 
  
394
 
  to.sin6_scope_id = (uint32_t)if_index;
395
 
  
 
363
  to.sin6_port = htons(port);
 
364
  to.sin6_scope_id = if_nametoindex(interface);
 
365
 
396
366
  if(debug){
397
367
    fprintf(stderr, "Connection to: %s\n", ip);
398
368
  }
408
378
    retval = -1;
409
379
    return -1;
410
380
  }
411
 
  
412
 
  gnutls_transport_set_ptr (es.session,
413
 
                            (gnutls_transport_ptr_t) tcp_sd);
414
 
  
 
381
    
 
382
  
 
383
  gnutls_transport_set_ptr (es.session, (gnutls_transport_ptr_t) tcp_sd);
 
384
 
415
385
  if(debug){
416
 
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
 
386
    fprintf(stderr, "Establishing tls session with %s\n", ip);
417
387
  }
 
388
 
418
389
  
419
390
  ret = gnutls_handshake (es.session);
420
391
  
421
392
  if (ret != GNUTLS_E_SUCCESS){
422
 
    if(debug){
423
 
      fprintf(stderr, "\n*** Handshake failed ***\n");
424
 
      gnutls_perror (ret);
425
 
    }
 
393
    fprintf(stderr, "\n*** Handshake failed ***\n");
 
394
    gnutls_perror (ret);
426
395
    retval = -1;
427
396
    goto exit;
428
397
  }
429
 
  
430
 
  //Retrieve OpenPGP packet that contains the wanted password
431
 
  
 
398
 
 
399
  //Retrieve gpg packet that contains the wanted password
 
400
 
432
401
  if(debug){
433
 
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n",
434
 
            ip);
 
402
    fprintf(stderr, "Retrieving pgp encrypted password from %s\n", ip);
435
403
  }
436
404
 
437
405
  while(true){
464
432
        }
465
433
        break;
466
434
      default:
467
 
        fprintf(stderr, "Unknown error while reading data from"
468
 
                " encrypted session with mandos server\n");
 
435
        fprintf(stderr, "Unknown error while reading data from encrypted session with mandos server\n");
469
436
        retval = -1;
470
437
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
471
438
        goto exit;
472
439
      }
473
440
    } else {
474
 
      buffer_length += (size_t) ret;
 
441
      buffer_length += ret;
475
442
    }
476
443
  }
477
444
  
478
445
  if (buffer_length > 0){
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
 
      }
 
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);
498
448
      free(decrypted_buffer);
499
449
    } else {
500
450
      retval = -1;
504
454
  //shutdown procedure
505
455
 
506
456
  if(debug){
507
 
    fprintf(stderr, "Closing TLS session\n");
 
457
    fprintf(stderr, "Closing tls session\n");
508
458
  }
509
459
 
510
460
  free(buffer);
522
472
 
523
473
static void resolve_callback(
524
474
    AvahiSServiceResolver *r,
525
 
    AvahiIfIndex interface,
 
475
    AVAHI_GCC_UNUSED AvahiIfIndex interface,
526
476
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
527
477
    AvahiResolverEvent event,
528
478
    const char *name,
531
481
    const char *host_name,
532
482
    const AvahiAddress *address,
533
483
    uint16_t port,
534
 
    AVAHI_GCC_UNUSED AvahiStringList *txt,
535
 
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
484
    AvahiStringList *txt,
 
485
    AvahiLookupResultFlags flags,
536
486
    AVAHI_GCC_UNUSED void* userdata) {
537
487
    
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
 
      }
 
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
        }
564
510
    }
565
 
  }
566
 
  avahi_s_service_resolver_free(r);
 
511
    avahi_s_service_resolver_free(r);
567
512
}
568
513
 
569
514
static void browse_callback(
578
523
    void* userdata) {
579
524
    
580
525
    AvahiServer *s = userdata;
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
 
    
 
526
    assert(b);
 
527
 
 
528
    /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
 
529
 
586
530
    switch (event) {
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;
 
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;
615
555
    }
616
556
}
617
557
 
621
561
    int error;
622
562
    int ret;
623
563
    int returncode = EXIT_SUCCESS;
624
 
    const char *interface = "eth0";
625
 
    
 
564
 
626
565
    while (true){
627
566
      static struct option long_options[] = {
628
567
        {"debug", no_argument, (int *)&debug, 1},
629
568
        {"interface", required_argument, 0, 'i'},
630
569
        {0, 0, 0, 0} };
631
 
      
 
570
 
632
571
      int option_index = 0;
633
 
      ret = getopt_long (argc, argv, "i:", long_options,
634
 
                         &option_index);
635
 
      
 
572
      ret = getopt_long (argc, argv, "i:", long_options, &option_index);
 
573
 
636
574
      if (ret == -1){
637
575
        break;
638
576
      }
653
591
    }
654
592
    
655
593
    /* Initialize the psuedo-RNG */
656
 
    srand((unsigned int) time(NULL));
 
594
    srand(time(NULL));
657
595
 
658
596
    /* Allocate main loop object */
659
597
    if (!(simple_poll = avahi_simple_poll_new())) {
670
608
    config.publish_domain = 0;
671
609
 
672
610
    /* Allocate a new server */
673
 
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
674
 
                              &config, NULL, NULL, &error);
 
611
    server = avahi_server_new(avahi_simple_poll_get(simple_poll), &config, NULL, NULL, &error);
675
612
 
676
613
    /* Free the configuration data */
677
614
    avahi_server_config_free(&config);
678
615
 
679
616
    /* Check if creating the server object succeeded */
680
617
    if (!server) {
681
 
        fprintf(stderr, "Failed to create server: %s\n",
682
 
                avahi_strerror(error));
 
618
        fprintf(stderr, "Failed to create server: %s\n", avahi_strerror(error));
683
619
        returncode = EXIT_FAILURE;
684
620
        goto exit;
685
621
    }
686
622
    
687
623
    /* Create the service browser */
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)));
 
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)));
697
626
        returncode = EXIT_FAILURE;
698
627
        goto exit;
699
628
    }
706
635
    
707
636
    avahi_simple_poll_loop(simple_poll);
708
637
    
709
 
 exit:
 
638
exit:
710
639
 
711
640
    if (debug){
712
641
      fprintf(stderr, "%s exiting\n", argv[0]);