/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-08-03 01:09:36 UTC
  • mfrom: (24.1.9 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20080803010936-ujme8tgxceszfbi1
* plugbasedclient.c (main): New "--userid" and "--groupid" options.
                            Take an additional non-option argument and
                            parse it as a plus-separated and -prefixed
                            list of additional options.

* plugins.d/mandosclient.c (DH_BITS): Replaced with
                                      "mandos_context.dh_bits".  All
                                      users changed.
  (certdir): Renamed to "keydir".  All users changed.
  (certfile): Renamed to "pubkeyfile".  All users changed.
  (certkey): Renamed to "seckeyfile".  All users changed.
  (encrypted_session): Replaced with "mandos_context".  All users
                       changed.
  (initgnutls): Take additional "session" and "dh_params" arguments.
                All callers changed.
  (start_mandos_communication): Take additional "mc" argument.  All
                                callers changed.  Print target IPv6
                                address if different than supplied
                                string.
  (simple_poll) Replaced with "mandos_context.simple_poll".  All users
                changed.
  (server): Replaced with "mandos_context.server".  All users changed.
  (main): Default interface to "eth0".  Rename "--certdir" to
          "--keydir", "--certkey" to "--seckey", and "--certfile" to
          "--pubkey".  New options "--dh-bits" and "--priority".  If
          the interface is not up, bring it up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
#include <errno.h>              /* perror() */
66
66
#include <gpgme.h>
67
67
 
68
 
// getopt long
 
68
// getopt_long
69
69
#include <getopt.h>
70
70
 
71
71
#define BUFFER_SIZE 256
72
 
#define DH_BITS 1024
73
72
 
74
 
static const char *certdir = "/conf/conf.d/mandos";
75
 
static const char *certfile = "openpgp-client.txt";
76
 
static const char *certkey = "openpgp-client-key.txt";
 
73
static const char *keydir = "/conf/conf.d/mandos";
 
74
static const char *pubkeyfile = "pubkey.txt";
 
75
static const char *seckeyfile = "seckey.txt";
77
76
 
78
77
bool debug = false;
79
78
 
 
79
/* Used for passing in values through all the callback functions */
80
80
typedef struct {
81
 
  gnutls_session_t session;
 
81
  AvahiSimplePoll *simple_poll;
 
82
  AvahiServer *server;
82
83
  gnutls_certificate_credentials_t cred;
83
 
  gnutls_dh_params_t dh_params;
84
 
} encrypted_session;
85
 
 
 
84
  unsigned int dh_bits;
 
85
  const char *priority;
 
86
} mandos_context;
86
87
 
87
88
static ssize_t pgp_packet_decrypt (char *packet, size_t packet_size,
88
89
                                   char **new_packet,
253
254
  fprintf(stderr, "%s", string);
254
255
}
255
256
 
256
 
static int initgnutls(encrypted_session *es){
 
257
static int initgnutls(mandos_context *mc, gnutls_session_t *session,
 
258
                      gnutls_dh_params_t *dh_params){
257
259
  const char *err;
258
260
  int ret;
259
261
  
266
268
    fprintf (stderr, "global_init: %s\n", safer_gnutls_strerror(ret));
267
269
    return -1;
268
270
  }
269
 
 
 
271
  
270
272
  if (debug){
271
273
    gnutls_global_set_log_level(11);
272
274
    gnutls_global_set_log_function(debuggnutls);
273
275
  }
274
276
  
275
277
  /* openpgp credentials */
276
 
  if ((ret = gnutls_certificate_allocate_credentials (&es->cred))
 
278
  if ((ret = gnutls_certificate_allocate_credentials (&mc->cred))
277
279
      != GNUTLS_E_SUCCESS) {
278
280
    fprintf (stderr, "memory error: %s\n",
279
281
             safer_gnutls_strerror(ret));
282
284
  
283
285
  if(debug){
284
286
    fprintf(stderr, "Attempting to use OpenPGP certificate %s"
285
 
            " and keyfile %s as GnuTLS credentials\n", certfile,
286
 
            certkey);
 
287
            " and keyfile %s as GnuTLS credentials\n", pubkeyfile,
 
288
            seckeyfile);
287
289
  }
288
290
  
289
291
  ret = gnutls_certificate_set_openpgp_key_file
290
 
    (es->cred, certfile, certkey, GNUTLS_OPENPGP_FMT_BASE64);
 
292
    (mc->cred, pubkeyfile, seckeyfile, GNUTLS_OPENPGP_FMT_BASE64);
291
293
  if (ret != GNUTLS_E_SUCCESS) {
292
294
    fprintf
293
295
      (stderr, "Error[%d] while reading the OpenPGP key pair ('%s',"
294
296
       " '%s')\n",
295
 
       ret, certfile, certkey);
 
297
       ret, pubkeyfile, seckeyfile);
296
298
    fprintf(stdout, "The Error is: %s\n",
297
299
            safer_gnutls_strerror(ret));
298
300
    return -1;
299
301
  }
300
302
  
301
303
  //GnuTLS server initialization
302
 
  if ((ret = gnutls_dh_params_init (&es->dh_params))
 
304
  if ((ret = gnutls_dh_params_init(dh_params))
303
305
      != GNUTLS_E_SUCCESS) {
304
306
    fprintf (stderr, "Error in dh parameter initialization: %s\n",
305
307
             safer_gnutls_strerror(ret));
306
308
    return -1;
307
309
  }
308
310
  
309
 
  if ((ret = gnutls_dh_params_generate2 (es->dh_params, DH_BITS))
 
311
  if ((ret = gnutls_dh_params_generate2(*dh_params, mc->dh_bits))
310
312
      != GNUTLS_E_SUCCESS) {
311
313
    fprintf (stderr, "Error in prime generation: %s\n",
312
314
             safer_gnutls_strerror(ret));
313
315
    return -1;
314
316
  }
315
317
  
316
 
  gnutls_certificate_set_dh_params (es->cred, es->dh_params);
 
318
  gnutls_certificate_set_dh_params(mc->cred, *dh_params);
317
319
  
318
320
  // GnuTLS session creation
319
 
  if ((ret = gnutls_init (&es->session, GNUTLS_SERVER))
 
321
  if ((ret = gnutls_init(session, GNUTLS_SERVER))
320
322
      != GNUTLS_E_SUCCESS){
321
323
    fprintf(stderr, "Error in GnuTLS session initialization: %s\n",
322
324
            safer_gnutls_strerror(ret));
323
325
  }
324
326
  
325
 
  if ((ret = gnutls_priority_set_direct (es->session, "NORMAL", &err))
 
327
  if ((ret = gnutls_priority_set_direct(*session, mc->priority, &err))
326
328
      != GNUTLS_E_SUCCESS) {
327
329
    fprintf(stderr, "Syntax error at: %s\n", err);
328
330
    fprintf(stderr, "GnuTLS error: %s\n",
330
332
    return -1;
331
333
  }
332
334
  
333
 
  if ((ret = gnutls_credentials_set
334
 
       (es->session, GNUTLS_CRD_CERTIFICATE, es->cred))
 
335
  if ((ret = gnutls_credentials_set(*session, GNUTLS_CRD_CERTIFICATE,
 
336
                                    mc->cred))
335
337
      != GNUTLS_E_SUCCESS) {
336
338
    fprintf(stderr, "Error setting a credentials set: %s\n",
337
339
            safer_gnutls_strerror(ret));
339
341
  }
340
342
  
341
343
  /* ignore client certificate if any. */
342
 
  gnutls_certificate_server_set_request (es->session,
 
344
  gnutls_certificate_server_set_request (*session,
343
345
                                         GNUTLS_CERT_IGNORE);
344
346
  
345
 
  gnutls_dh_set_prime_bits (es->session, DH_BITS);
 
347
  gnutls_dh_set_prime_bits (*session, mc->dh_bits);
346
348
  
347
349
  return 0;
348
350
}
351
353
                      __attribute__((unused)) const char *txt){}
352
354
 
353
355
static int start_mandos_communication(const char *ip, uint16_t port,
354
 
                                      AvahiIfIndex if_index){
 
356
                                      AvahiIfIndex if_index,
 
357
                                      mandos_context *mc){
355
358
  int ret, tcp_sd;
356
359
  struct sockaddr_in6 to;
357
 
  encrypted_session es;
358
360
  char *buffer = NULL;
359
361
  char *decrypted_buffer;
360
362
  size_t buffer_length = 0;
363
365
  size_t written = 0;
364
366
  int retval = 0;
365
367
  char interface[IF_NAMESIZE];
 
368
  gnutls_session_t session;
 
369
  gnutls_dh_params_t dh_params;
366
370
  
367
371
  if(debug){
368
372
    fprintf(stderr, "Setting up a tcp connection to %s, port %d\n",
377
381
 
378
382
  if(debug){
379
383
    if(if_indextoname((unsigned int)if_index, interface) == NULL){
380
 
      if(debug){
381
 
        perror("if_indextoname");
382
 
      }
 
384
      perror("if_indextoname");
383
385
      return -1;
384
386
    }
385
 
    
386
387
    fprintf(stderr, "Binding to interface %s\n", interface);
387
388
  }
388
389
  
392
393
  if (ret < 0 ){
393
394
    perror("inet_pton");
394
395
    return -1;
395
 
  }  
 
396
  }
396
397
  if(ret == 0){
397
398
    fprintf(stderr, "Bad address: %s\n", ip);
398
399
    return -1;
403
404
  
404
405
  if(debug){
405
406
    fprintf(stderr, "Connection to: %s, port %d\n", ip, port);
406
 
/*     char addrstr[INET6_ADDRSTRLEN]; */
407
 
/*     if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr, */
408
 
/*               sizeof(addrstr)) == NULL){ */
409
 
/*       perror("inet_ntop"); */
410
 
/*     } else { */
411
 
/*       fprintf(stderr, "Really connecting to: %s, port %d\n", */
412
 
/*            addrstr, ntohs(to.sin6_port)); */
413
 
/*     } */
 
407
    char addrstr[INET6_ADDRSTRLEN] = "";
 
408
    if(inet_ntop(to.sin6_family, &(to.sin6_addr), addrstr,
 
409
                 sizeof(addrstr)) == NULL){
 
410
      perror("inet_ntop");
 
411
    } else {
 
412
      if(strcmp(addrstr, ip) != 0){
 
413
        fprintf(stderr, "Canonical address form: %s\n", addrstr);
 
414
      }
 
415
    }
414
416
  }
415
417
  
416
418
  ret = connect(tcp_sd, (struct sockaddr *) &to, sizeof(to));
419
421
    return -1;
420
422
  }
421
423
  
422
 
  ret = initgnutls (&es);
 
424
  ret = initgnutls (mc, &session, &dh_params);
423
425
  if (ret != 0){
424
426
    retval = -1;
425
427
    return -1;
426
428
  }
427
429
  
428
 
  gnutls_transport_set_ptr (es.session,
429
 
                            (gnutls_transport_ptr_t) tcp_sd);
 
430
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) tcp_sd);
430
431
  
431
432
  if(debug){
432
433
    fprintf(stderr, "Establishing TLS session with %s\n", ip);
433
434
  }
434
435
  
435
 
  ret = gnutls_handshake (es.session);
 
436
  ret = gnutls_handshake (session);
436
437
  
437
438
  if (ret != GNUTLS_E_SUCCESS){
438
439
    if(debug){
460
461
      buffer_capacity += BUFFER_SIZE;
461
462
    }
462
463
    
463
 
    ret = gnutls_record_recv
464
 
      (es.session, buffer+buffer_length, BUFFER_SIZE);
 
464
    ret = gnutls_record_recv(session, buffer+buffer_length,
 
465
                             BUFFER_SIZE);
465
466
    if (ret == 0){
466
467
      break;
467
468
    }
471
472
      case GNUTLS_E_AGAIN:
472
473
        break;
473
474
      case GNUTLS_E_REHANDSHAKE:
474
 
        ret = gnutls_handshake (es.session);
 
475
        ret = gnutls_handshake (session);
475
476
        if (ret < 0){
476
477
          fprintf(stderr, "\n*** Handshake failed ***\n");
477
478
          gnutls_perror (ret);
483
484
        fprintf(stderr, "Unknown error while reading data from"
484
485
                " encrypted session with mandos server\n");
485
486
        retval = -1;
486
 
        gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
 
487
        gnutls_bye (session, GNUTLS_SHUT_RDWR);
487
488
        goto exit;
488
489
      }
489
490
    } else {
495
496
    decrypted_buffer_size = pgp_packet_decrypt(buffer,
496
497
                                               buffer_length,
497
498
                                               &decrypted_buffer,
498
 
                                               certdir);
 
499
                                               keydir);
499
500
    if (decrypted_buffer_size >= 0){
500
501
      while(written < (size_t) decrypted_buffer_size){
501
502
        ret = (int)fwrite (decrypted_buffer + written, 1,
524
525
  }
525
526
 
526
527
  free(buffer);
527
 
  gnutls_bye (es.session, GNUTLS_SHUT_RDWR);
 
528
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
528
529
 exit:
529
530
  close(tcp_sd);
530
 
  gnutls_deinit (es.session);
531
 
  gnutls_certificate_free_credentials (es.cred);
 
531
  gnutls_deinit (session);
 
532
  gnutls_certificate_free_credentials (mc->cred);
532
533
  gnutls_global_deinit ();
533
534
  return retval;
534
535
}
535
536
 
536
 
static AvahiSimplePoll *simple_poll = NULL;
537
 
static AvahiServer *server = NULL;
538
 
 
539
 
static void resolve_callback(
540
 
    AvahiSServiceResolver *r,
541
 
    AvahiIfIndex interface,
542
 
    AVAHI_GCC_UNUSED AvahiProtocol protocol,
543
 
    AvahiResolverEvent event,
544
 
    const char *name,
545
 
    const char *type,
546
 
    const char *domain,
547
 
    const char *host_name,
548
 
    const AvahiAddress *address,
549
 
    uint16_t port,
550
 
    AVAHI_GCC_UNUSED AvahiStringList *txt,
551
 
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
552
 
    AVAHI_GCC_UNUSED void* userdata) {
553
 
    
 
537
static void resolve_callback( AvahiSServiceResolver *r,
 
538
                              AvahiIfIndex interface,
 
539
                              AVAHI_GCC_UNUSED AvahiProtocol protocol,
 
540
                              AvahiResolverEvent event,
 
541
                              const char *name,
 
542
                              const char *type,
 
543
                              const char *domain,
 
544
                              const char *host_name,
 
545
                              const AvahiAddress *address,
 
546
                              uint16_t port,
 
547
                              AVAHI_GCC_UNUSED AvahiStringList *txt,
 
548
                              AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
549
                              void* userdata) {
 
550
  mandos_context *mc = userdata;
554
551
  assert(r);                    /* Spurious warning */
555
552
  
556
553
  /* Called whenever a service has been resolved successfully or
561
558
  case AVAHI_RESOLVER_FAILURE:
562
559
    fprintf(stderr, "(Resolver) Failed to resolve service '%s' of"
563
560
            " type '%s' in domain '%s': %s\n", name, type, domain,
564
 
            avahi_strerror(avahi_server_errno(server)));
 
561
            avahi_strerror(avahi_server_errno(mc->server)));
565
562
    break;
566
563
    
567
564
  case AVAHI_RESOLVER_FOUND:
572
569
        fprintf(stderr, "Mandos server \"%s\" found on %s (%s) on"
573
570
                " port %d\n", name, host_name, ip, port);
574
571
      }
575
 
      int ret = start_mandos_communication(ip, port, interface);
 
572
      int ret = start_mandos_communication(ip, port, interface, mc);
576
573
      if (ret == 0){
577
574
        exit(EXIT_SUCCESS);
578
575
      }
581
578
  avahi_s_service_resolver_free(r);
582
579
}
583
580
 
584
 
static void browse_callback(
585
 
    AvahiSServiceBrowser *b,
586
 
    AvahiIfIndex interface,
587
 
    AvahiProtocol protocol,
588
 
    AvahiBrowserEvent event,
589
 
    const char *name,
590
 
    const char *type,
591
 
    const char *domain,
592
 
    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
593
 
    void* userdata) {
594
 
    
595
 
    AvahiServer *s = userdata;
596
 
    assert(b);                  /* Spurious warning */
597
 
    
598
 
    /* Called whenever a new services becomes available on the LAN or
599
 
       is removed from the LAN */
600
 
    
601
 
    switch (event) {
602
 
    default:
603
 
    case AVAHI_BROWSER_FAILURE:
604
 
      
605
 
      fprintf(stderr, "(Browser) %s\n",
606
 
              avahi_strerror(avahi_server_errno(server)));
607
 
      avahi_simple_poll_quit(simple_poll);
608
 
      return;
609
 
      
610
 
    case AVAHI_BROWSER_NEW:
611
 
      /* We ignore the returned resolver object. In the callback
612
 
         function we free it. If the server is terminated before
613
 
         the callback function is called the server will free
614
 
         the resolver for us. */
615
 
      
616
 
      if (!(avahi_s_service_resolver_new(s, interface, protocol, name,
617
 
                                         type, domain,
618
 
                                         AVAHI_PROTO_INET6, 0,
619
 
                                         resolve_callback, s)))
620
 
        fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
621
 
                avahi_strerror(avahi_server_errno(s)));
622
 
      break;
623
 
      
624
 
    case AVAHI_BROWSER_REMOVE:
625
 
      break;
626
 
      
627
 
    case AVAHI_BROWSER_ALL_FOR_NOW:
628
 
    case AVAHI_BROWSER_CACHE_EXHAUSTED:
629
 
      break;
630
 
    }
 
581
static void browse_callback( AvahiSServiceBrowser *b,
 
582
                             AvahiIfIndex interface,
 
583
                             AvahiProtocol protocol,
 
584
                             AvahiBrowserEvent event,
 
585
                             const char *name,
 
586
                             const char *type,
 
587
                             const char *domain,
 
588
                             AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
 
589
                             void* userdata) {
 
590
  mandos_context *mc = userdata;
 
591
  assert(b);                    /* Spurious warning */
 
592
  
 
593
  /* Called whenever a new services becomes available on the LAN or
 
594
     is removed from the LAN */
 
595
  
 
596
  switch (event) {
 
597
  default:
 
598
  case AVAHI_BROWSER_FAILURE:
 
599
    
 
600
    fprintf(stderr, "(Browser) %s\n",
 
601
            avahi_strerror(avahi_server_errno(mc->server)));
 
602
    avahi_simple_poll_quit(mc->simple_poll);
 
603
    return;
 
604
    
 
605
  case AVAHI_BROWSER_NEW:
 
606
    /* We ignore the returned resolver object. In the callback
 
607
       function we free it. If the server is terminated before
 
608
       the callback function is called the server will free
 
609
       the resolver for us. */
 
610
    
 
611
    if (!(avahi_s_service_resolver_new(mc->server, interface, protocol, name,
 
612
                                       type, domain,
 
613
                                       AVAHI_PROTO_INET6, 0,
 
614
                                       resolve_callback, mc)))
 
615
      fprintf(stderr, "Failed to resolve service '%s': %s\n", name,
 
616
              avahi_strerror(avahi_server_errno(mc->server)));
 
617
    break;
 
618
    
 
619
  case AVAHI_BROWSER_REMOVE:
 
620
    break;
 
621
    
 
622
  case AVAHI_BROWSER_ALL_FOR_NOW:
 
623
  case AVAHI_BROWSER_CACHE_EXHAUSTED:
 
624
    break;
 
625
  }
631
626
}
632
627
 
633
628
/* Combines file name and path and returns the malloced new
640
635
    return NULL;
641
636
  }
642
637
  if(f_len > 0){
643
 
    memcpy(tmp, first, f_len);
 
638
    memcpy(tmp, first, f_len);  /* Spurious warning */
644
639
  }
645
640
  tmp[f_len] = '/';
646
641
  if(s_len > 0){
647
 
    memcpy(tmp + f_len + 1, second, s_len);
 
642
    memcpy(tmp + f_len + 1, second, s_len); /* Spurious warning */
648
643
  }
649
644
  tmp[f_len + 1 + s_len] = '\0';
650
645
  return tmp;
656
651
    AvahiSServiceBrowser *sb = NULL;
657
652
    int error;
658
653
    int ret;
 
654
    int debug_int;
659
655
    int returncode = EXIT_SUCCESS;
660
656
    const char *interface = "eth0";
661
657
    struct ifreq network;
662
658
    int sd;
663
659
    char *connect_to = NULL;
664
660
    AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
 
661
    mandos_context mc = { .simple_poll = NULL, .server = NULL,
 
662
                          .dh_bits = 1024, .priority = "SECURE256"};
665
663
    
 
664
    debug_int = debug ? 1 : 0;
666
665
    while (true){
667
 
      static struct option long_options[] = {
668
 
        {"debug", no_argument, (int *)&debug, 1},
669
 
        {"connect", required_argument, 0, 'C'},
670
 
        {"interface", required_argument, 0, 'i'},
671
 
        {"certdir", required_argument, 0, 'd'},
672
 
        {"certkey", required_argument, 0, 'c'},
673
 
        {"certfile", required_argument, 0, 'k'},
 
666
      struct option long_options[] = {
 
667
        {"debug", no_argument, &debug_int, 1},
 
668
        {"connect", required_argument, NULL, 'c'},
 
669
        {"interface", required_argument, NULL, 'i'},
 
670
        {"keydir", required_argument, NULL, 'd'},
 
671
        {"seckey", required_argument, NULL, 's'},
 
672
        {"pubkey", required_argument, NULL, 'p'},
 
673
        {"dh-bits", required_argument, NULL, 'D'},
 
674
        {"priority", required_argument, NULL, 'P'},
674
675
        {0, 0, 0, 0} };
675
676
      
676
677
      int option_index = 0;
687
688
      case 'i':
688
689
        interface = optarg;
689
690
        break;
690
 
      case 'C':
 
691
      case 'c':
691
692
        connect_to = optarg;
692
693
        break;
693
694
      case 'd':
694
 
        certdir = optarg;
695
 
        break;
696
 
      case 'c':
697
 
        certfile = optarg;
698
 
        break;
699
 
      case 'k':
700
 
        certkey = optarg;
701
 
        break;
 
695
        keydir = optarg;
 
696
        break;
 
697
      case 'p':
 
698
        pubkeyfile = optarg;
 
699
        break;
 
700
      case 's':
 
701
        seckeyfile = optarg;
 
702
        break;
 
703
      case 'D':
 
704
        errno = 0;
 
705
        mc.dh_bits = (unsigned int) strtol(optarg, NULL, 10);
 
706
        if (errno){
 
707
          perror("strtol");
 
708
          exit(EXIT_FAILURE);
 
709
        }
 
710
        break;
 
711
      case 'P':
 
712
        mc.priority = optarg;
 
713
        break;
 
714
      case '?':
702
715
      default:
703
716
        exit(EXIT_FAILURE);
704
717
      }
705
718
    }
 
719
    debug = debug_int ? true : false;
706
720
    
707
 
    certfile = combinepath(certdir, certfile);
708
 
    if (certfile == NULL){
 
721
    pubkeyfile = combinepath(keydir, pubkeyfile);
 
722
    if (pubkeyfile == NULL){
709
723
      perror("combinepath");
710
724
      returncode = EXIT_FAILURE;
711
725
      goto exit;
712
726
    }
713
 
 
714
 
    certkey = combinepath(certdir, certkey);
715
 
    if (certkey == NULL){
 
727
    
 
728
    seckeyfile = combinepath(keydir, seckeyfile);
 
729
    if (seckeyfile == NULL){
716
730
      perror("combinepath");
717
 
      returncode = EXIT_FAILURE;
718
731
      goto exit;
719
732
    }
720
733
    
740
753
      }
741
754
      *address = '\0';
742
755
      address = connect_to;
743
 
      ret = start_mandos_communication(address, port, if_index);
 
756
      ret = start_mandos_communication(address, port, if_index, &mc);
744
757
      if(ret < 0){
745
758
        exit(EXIT_FAILURE);
746
759
      } else {
754
767
      returncode = EXIT_FAILURE;
755
768
      goto exit;
756
769
    }
757
 
    strcpy(network.ifr_name, interface);    
 
770
    strcpy(network.ifr_name, interface); /* Spurious warning */
758
771
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
759
772
    if(ret == -1){
760
773
      
781
794
    srand((unsigned int) time(NULL));
782
795
 
783
796
    /* Allocate main loop object */
784
 
    if (!(simple_poll = avahi_simple_poll_new())) {
 
797
    if (!(mc.simple_poll = avahi_simple_poll_new())) {
785
798
        fprintf(stderr, "Failed to create simple poll object.\n");
786
 
        returncode = EXIT_FAILURE;      
 
799
        returncode = EXIT_FAILURE;
787
800
        goto exit;
788
801
    }
789
802
 
795
808
    config.publish_domain = 0;
796
809
 
797
810
    /* Allocate a new server */
798
 
    server = avahi_server_new(avahi_simple_poll_get(simple_poll),
799
 
                              &config, NULL, NULL, &error);
800
 
 
 
811
    mc.server=avahi_server_new(avahi_simple_poll_get(mc.simple_poll),
 
812
                               &config, NULL, NULL, &error);
 
813
    
801
814
    /* Free the configuration data */
802
815
    avahi_server_config_free(&config);
803
 
 
 
816
    
804
817
    /* Check if creating the server object succeeded */
805
 
    if (!server) {
 
818
    if (!mc.server) {
806
819
        fprintf(stderr, "Failed to create server: %s\n",
807
820
                avahi_strerror(error));
808
821
        returncode = EXIT_FAILURE;
810
823
    }
811
824
    
812
825
    /* Create the service browser */
813
 
    sb = avahi_s_service_browser_new(server, if_index,
 
826
    sb = avahi_s_service_browser_new(mc.server, if_index,
814
827
                                     AVAHI_PROTO_INET6,
815
828
                                     "_mandos._tcp", NULL, 0,
816
 
                                     browse_callback, server);
 
829
                                     browse_callback, &mc);
817
830
    if (!sb) {
818
831
        fprintf(stderr, "Failed to create service browser: %s\n",
819
 
                avahi_strerror(avahi_server_errno(server)));
 
832
                avahi_strerror(avahi_server_errno(mc.server)));
820
833
        returncode = EXIT_FAILURE;
821
834
        goto exit;
822
835
    }
827
840
      fprintf(stderr, "Starting avahi loop search\n");
828
841
    }
829
842
    
830
 
    avahi_simple_poll_loop(simple_poll);
 
843
    avahi_simple_poll_loop(mc.simple_poll);
831
844
    
832
845
 exit:
833
846
 
839
852
    if (sb)
840
853
        avahi_s_service_browser_free(sb);
841
854
    
842
 
    if (server)
843
 
        avahi_server_free(server);
 
855
    if (mc.server)
 
856
        avahi_server_free(mc.server);
844
857
 
845
 
    if (simple_poll)
846
 
        avahi_simple_poll_free(simple_poll);
847
 
    free(certfile);
848
 
    free(certkey);
 
858
    if (mc.simple_poll)
 
859
        avahi_simple_poll_free(mc.simple_poll);
 
860
    free(pubkeyfile);
 
861
    free(seckeyfile);
849
862
    
850
863
    return returncode;
851
864
}