/mandos/release

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

« back to all changes in this revision

Viewing changes to plugins.d/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2012-06-09 23:41:07 UTC
  • mto: (237.7.144 trunk)
  • mto: This revision was merged to the branch mainline in revision 302.
  • Revision ID: teddy@recompile.se-20120609234107-vm6zilzz0y6aihsm
* plugins.d/mandos-client.c (raise_privileges,
  raise_privileges_permanently, lower_privileges): Return error_t and
                                                   save old errno
                                                   before calling any
                                                   other function.

Show diffs side-by-side

added added

removed removed

Lines of Context:
88
88
#include <sys/wait.h>           /* waitpid(), WIFEXITED(),
89
89
                                   WEXITSTATUS(), WTERMSIG() */
90
90
#include <grp.h>                /* setgroups() */
91
 
#include <argz.h>               /* argz_add_sep(), argz_next(),
92
 
                                   argz_delete(), argz_append(),
93
 
                                   argz_stringify(), argz_add(),
94
 
                                   argz_count() */
95
91
 
96
92
#ifdef __linux__
97
93
#include <sys/klog.h>           /* klogctl() */
1125
1121
 
1126
1122
bool get_flags(const char *ifname, struct ifreq *ifr){
1127
1123
  int ret;
1128
 
  error_t ret_errno;
1129
1124
  
1130
1125
  int s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1131
1126
  if(s < 0){
1132
 
    ret_errno = errno;
1133
1127
    perror_plus("socket");
1134
 
    errno = ret_errno;
1135
1128
    return false;
1136
1129
  }
1137
1130
  strcpy(ifr->ifr_name, ifname);
1138
1131
  ret = ioctl(s, SIOCGIFFLAGS, ifr);
1139
1132
  if(ret == -1){
1140
1133
    if(debug){
1141
 
      ret_errno = errno;
1142
1134
      perror_plus("ioctl SIOCGIFFLAGS");
1143
 
      errno = ret_errno;
1144
1135
    }
1145
1136
    return false;
1146
1137
  }
1215
1206
}
1216
1207
 
1217
1208
/* 
1218
 
 * This function determines if a network interface is up.
1219
 
 */
1220
 
bool interface_is_up(const char *interface){
1221
 
  struct ifreq ifr;
1222
 
  if(not get_flags(interface, &ifr)){
1223
 
    if(debug){
1224
 
      fprintf_plus(stderr, "Failed to get flags for interface "
1225
 
                   "\"%s\"\n", interface);
1226
 
    }
1227
 
    return false;
1228
 
  }
1229
 
  
1230
 
  return (bool)(ifr.ifr_flags & IFF_UP);
1231
 
}
1232
 
 
1233
 
/* 
1234
 
 * This function determines if a network interface is running
1235
 
 */
1236
 
bool interface_is_running(const char *interface){
1237
 
  struct ifreq ifr;
1238
 
  if(not get_flags(interface, &ifr)){
1239
 
    if(debug){
1240
 
      fprintf_plus(stderr, "Failed to get flags for interface "
1241
 
                   "\"%s\"\n", interface);
1242
 
    }
1243
 
    return false;
1244
 
  }
1245
 
  
1246
 
  return (bool)(ifr.ifr_flags & IFF_RUNNING);
 
1209
 * This function determines if a directory entry in /sys/class/net
 
1210
 * corresponds to an acceptable network device which is up.
 
1211
 * (This function is passed to scandir(3) as a filter function.)
 
1212
 */
 
1213
int up_interface(const struct dirent *if_entry){
 
1214
  if(if_entry->d_name[0] == '.'){
 
1215
    return 0;
 
1216
  }
 
1217
  
 
1218
  struct ifreq ifr;
 
1219
  if(not get_flags(if_entry->d_name, &ifr)){
 
1220
    if(debug){
 
1221
      fprintf_plus(stderr, "Failed to get flags for interface "
 
1222
                   "\"%s\"\n", if_entry->d_name);
 
1223
    }
 
1224
    return 0;
 
1225
  }
 
1226
  
 
1227
  /* Reject down interfaces */
 
1228
  if(not (ifr.ifr_flags & IFF_UP)){
 
1229
    if(debug){
 
1230
      fprintf_plus(stderr, "Rejecting down interface \"%s\"\n",
 
1231
                   if_entry->d_name);
 
1232
    }
 
1233
    return 0;
 
1234
  }
 
1235
  
 
1236
  /* Reject non-running interfaces */
 
1237
  if(not (ifr.ifr_flags & IFF_RUNNING)){
 
1238
    if(debug){
 
1239
      fprintf_plus(stderr, "Rejecting non-running interface \"%s\"\n",
 
1240
                   if_entry->d_name);
 
1241
    }
 
1242
    return 0;
 
1243
  }
 
1244
  
 
1245
  if(not good_flags(if_entry->d_name, &ifr)){
 
1246
    return 0;
 
1247
  }
 
1248
  return 1;
1247
1249
}
1248
1250
 
1249
1251
int notdotentries(const struct dirent *direntry){
1430
1432
  return ret_errno;
1431
1433
}
1432
1434
 
1433
 
/* Lower privileges permanently */
1434
 
error_t lower_privileges_permanently(void){
1435
 
  error_t old_errno = errno;
1436
 
  error_t ret_errno = 0;
1437
 
  if(setuid(uid) == -1){
1438
 
    ret_errno = errno;
1439
 
    perror_plus("setuid");
1440
 
  }
1441
 
  errno = old_errno;
1442
 
  return ret_errno;
1443
 
}
1444
 
 
1445
1435
bool run_network_hooks(const char *mode, const char *interface,
1446
1436
                       const float delay){
1447
1437
  struct dirent **direntries;
1568
1558
  return true;
1569
1559
}
1570
1560
 
1571
 
error_t bring_up_interface(const char *const interface,
1572
 
                           const float delay){
 
1561
int bring_up_interface(const char *const interface,
 
1562
                       const float delay){
1573
1563
  int sd = -1;
1574
 
  error_t old_errno = errno;
1575
 
  error_t ret_errno = 0;
1576
 
  int ret, ret_setflags;
 
1564
  int old_errno = errno;
 
1565
  int ret_errno = 0;
 
1566
  int ret;
1577
1567
  struct ifreq network;
1578
 
  unsigned int if_index = if_nametoindex(interface);
 
1568
  AvahiIfIndex if_index = (AvahiIfIndex)if_nametoindex(interface);
1579
1569
  if(if_index == 0){
1580
1570
    fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
1581
1571
    errno = old_errno;
1587
1577
    return EINTR;
1588
1578
  }
1589
1579
  
1590
 
  if(not interface_is_up(interface)){
1591
 
    if(not get_flags(interface, &network) and debug){
1592
 
      ret_errno = errno;
1593
 
      fprintf_plus(stderr, "Failed to get flags for interface "
1594
 
                   "\"%s\"\n", interface);
1595
 
      return ret_errno;
1596
 
    }
 
1580
  /* Re-raise priviliges */
 
1581
  raise_privileges();
 
1582
  
 
1583
#ifdef __linux__
 
1584
  /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
 
1585
     messages about the network interface to mess up the prompt */
 
1586
  ret = klogctl(8, NULL, 5);
 
1587
  bool restore_loglevel = true;
 
1588
  if(ret == -1){
 
1589
    restore_loglevel = false;
 
1590
    perror_plus("klogctl");
 
1591
  }
 
1592
#endif  /* __linux__ */
 
1593
    
 
1594
  sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
 
1595
  if(sd < 0){
 
1596
    ret_errno = errno;
 
1597
    perror_plus("socket");
 
1598
#ifdef __linux__
 
1599
    if(restore_loglevel){
 
1600
      ret = klogctl(7, NULL, 0);
 
1601
      if(ret == -1){
 
1602
        perror_plus("klogctl");
 
1603
      }
 
1604
    }
 
1605
#endif  /* __linux__ */
 
1606
    /* Lower privileges */
 
1607
    lower_privileges();
 
1608
    errno = old_errno;
 
1609
    return ret_errno;
 
1610
  }
 
1611
  strcpy(network.ifr_name, interface);
 
1612
  ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
1613
  if(ret == -1){
 
1614
    ret_errno = errno;
 
1615
    perror_plus("ioctl SIOCGIFFLAGS");
 
1616
#ifdef __linux__
 
1617
    if(restore_loglevel){
 
1618
      ret = klogctl(7, NULL, 0);
 
1619
      if(ret == -1){
 
1620
        perror_plus("klogctl");
 
1621
      }
 
1622
    }
 
1623
#endif  /* __linux__ */
 
1624
    /* Lower privileges */
 
1625
    lower_privileges();
 
1626
    errno = old_errno;
 
1627
    return ret_errno;
 
1628
  }
 
1629
  if((network.ifr_flags & IFF_UP) == 0){
1597
1630
    network.ifr_flags |= IFF_UP;
1598
 
    
1599
 
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1600
 
    if(sd < 0){
 
1631
    ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
1632
    if(ret == -1){
1601
1633
      ret_errno = errno;
1602
 
      perror_plus("socket");
1603
 
      errno = old_errno;
1604
 
      return ret_errno;
1605
 
    }
1606
 
  
1607
 
    if(quit_now){
1608
 
      close(sd);
1609
 
      errno = old_errno;
1610
 
      return EINTR;
1611
 
    }
1612
 
    
1613
 
    if(debug){
1614
 
      fprintf_plus(stderr, "Bringing up interface \"%s\"\n",
1615
 
                   interface);
1616
 
    }
1617
 
    
1618
 
    /* Raise priviliges */
1619
 
    raise_privileges();
1620
 
    
1621
 
#ifdef __linux__
1622
 
    /* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
1623
 
       messages about the network interface to mess up the prompt */
1624
 
    int ret_linux = klogctl(8, NULL, 5);
1625
 
    bool restore_loglevel = true;
1626
 
    if(ret_linux == -1){
1627
 
      restore_loglevel = false;
1628
 
      perror_plus("klogctl");
1629
 
    }
1630
 
#endif  /* __linux__ */
1631
 
    ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
1632
 
    ret_errno = errno;
1633
 
#ifdef __linux__
1634
 
    if(restore_loglevel){
1635
 
      ret_linux = klogctl(7, NULL, 0);
1636
 
      if(ret_linux == -1){
1637
 
        perror_plus("klogctl");
1638
 
      }
1639
 
    }
1640
 
#endif  /* __linux__ */
1641
 
    
1642
 
    /* Lower privileges */
1643
 
    lower_privileges();
1644
 
    
1645
 
    /* Close the socket */
1646
 
    ret = (int)TEMP_FAILURE_RETRY(close(sd));
1647
 
    if(ret == -1){
1648
 
      perror_plus("close");
1649
 
    }
1650
 
    
1651
 
    if(ret_setflags == -1){
1652
 
      errno = ret_errno;
1653
1634
      perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
 
1635
#ifdef __linux__
 
1636
      if(restore_loglevel){
 
1637
        ret = klogctl(7, NULL, 0);
 
1638
        if(ret == -1){
 
1639
          perror_plus("klogctl");
 
1640
        }
 
1641
      }
 
1642
#endif  /* __linux__ */
 
1643
        /* Lower privileges */
 
1644
      lower_privileges();
1654
1645
      errno = old_errno;
1655
1646
      return ret_errno;
1656
1647
    }
1657
 
  } else if(debug){
1658
 
    fprintf_plus(stderr, "Interface \"%s\" is already up; good\n",
1659
 
                 interface);
1660
1648
  }
1661
 
  
1662
1649
  /* Sleep checking until interface is running.
1663
1650
     Check every 0.25s, up to total time of delay */
1664
1651
  for(int i=0; i < delay * 4; i++){
1665
 
    if(interface_is_running(interface)){
 
1652
    ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
1653
    if(ret == -1){
 
1654
      perror_plus("ioctl SIOCGIFFLAGS");
 
1655
    } else if(network.ifr_flags & IFF_RUNNING){
1666
1656
      break;
1667
1657
    }
1668
1658
    struct timespec sleeptime = { .tv_nsec = 250000000 };
1671
1661
      perror_plus("nanosleep");
1672
1662
    }
1673
1663
  }
1674
 
  
1675
 
  errno = old_errno;
1676
 
  return 0;
1677
 
}
1678
 
 
1679
 
error_t take_down_interface(const char *const interface){
1680
 
  int sd = -1;
1681
 
  error_t old_errno = errno;
1682
 
  error_t ret_errno = 0;
1683
 
  int ret, ret_setflags;
1684
 
  struct ifreq network;
1685
 
  unsigned int if_index = if_nametoindex(interface);
1686
 
  if(if_index == 0){
1687
 
    fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
1688
 
    errno = old_errno;
1689
 
    return ENXIO;
 
1664
  /* Close the socket */
 
1665
  ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
1666
  if(ret == -1){
 
1667
    perror_plus("close");
1690
1668
  }
1691
 
  if(interface_is_up(interface)){
1692
 
    if(not get_flags(interface, &network) and debug){
1693
 
      ret_errno = errno;
1694
 
      fprintf_plus(stderr, "Failed to get flags for interface "
1695
 
                   "\"%s\"\n", interface);
1696
 
      return ret_errno;
1697
 
    }
1698
 
    network.ifr_flags &= ~(short)IFF_UP; /* clear flag */
1699
 
    
1700
 
    sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1701
 
    if(sd < 0){
1702
 
      ret_errno = errno;
1703
 
      perror_plus("socket");
1704
 
      errno = old_errno;
1705
 
      return ret_errno;
1706
 
    }
1707
 
    
1708
 
    if(debug){
1709
 
      fprintf_plus(stderr, "Taking down interface \"%s\"\n",
1710
 
                   interface);
1711
 
    }
1712
 
    
1713
 
    /* Raise priviliges */
1714
 
    raise_privileges();
1715
 
    
1716
 
    ret_setflags = ioctl(sd, SIOCSIFFLAGS, &network);
1717
 
    ret_errno = errno;
1718
 
    
1719
 
    /* Lower privileges */
1720
 
    lower_privileges();
1721
 
    
1722
 
    /* Close the socket */
1723
 
    ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
1669
#ifdef __linux__
 
1670
  if(restore_loglevel){
 
1671
    /* Restores kernel loglevel to default */
 
1672
    ret = klogctl(7, NULL, 0);
1724
1673
    if(ret == -1){
1725
 
      perror_plus("close");
1726
 
    }
1727
 
    
1728
 
    if(ret_setflags == -1){
1729
 
      errno = ret_errno;
1730
 
      perror_plus("ioctl SIOCSIFFLAGS -IFF_UP");
1731
 
      errno = old_errno;
1732
 
      return ret_errno;
1733
 
    }
1734
 
  } else if(debug){
1735
 
    fprintf_plus(stderr, "Interface \"%s\" is already down; odd\n",
1736
 
                 interface);
 
1674
      perror_plus("klogctl");
 
1675
    }
1737
1676
  }
1738
 
  
 
1677
#endif  /* __linux__ */
 
1678
  /* Lower privileges */
 
1679
  lower_privileges();
1739
1680
  errno = old_errno;
1740
1681
  return 0;
1741
1682
}
1742
1683
 
1743
1684
int main(int argc, char *argv[]){
1744
1685
  AvahiSServiceBrowser *sb = NULL;
1745
 
  error_t ret_errno;
 
1686
  int error;
1746
1687
  int ret;
1747
1688
  intmax_t tmpmax;
1748
1689
  char *tmp;
1749
1690
  int exitcode = EXIT_SUCCESS;
1750
 
  char *interfaces = NULL;
1751
 
  size_t interfaces_size = 0;
1752
 
  char *interfaces_to_take_down = NULL;
1753
 
  size_t interfaces_to_take_down_size = 0;
 
1691
  const char *interface = "";
 
1692
  struct ifreq network;
 
1693
  int sd = -1;
 
1694
  bool take_down_interface = false;
1754
1695
  char tempdir[] = "/tmp/mandosXXXXXX";
1755
1696
  bool tempdir_created = false;
1756
1697
  AvahiIfIndex if_index = AVAHI_IF_UNSPEC;
1757
1698
  const char *seckey = PATHDIR "/" SECKEY;
1758
1699
  const char *pubkey = PATHDIR "/" PUBKEY;
1759
 
  char *interfaces_hooks = NULL;
1760
 
  size_t interfaces_hooks_size = 0;
1761
1700
  
1762
1701
  bool gnutls_initialized = false;
1763
1702
  bool gpgme_initialized = false;
1854
1793
        connect_to = arg;
1855
1794
        break;
1856
1795
      case 'i':                 /* --interface */
1857
 
        ret_errno = argz_add_sep(&interfaces, &interfaces_size, arg,
1858
 
                                 (int)',');
1859
 
        if(ret_errno != 0){
1860
 
          argp_error(state, "%s", strerror(ret_errno));
1861
 
        }
 
1796
        interface = arg;
1862
1797
        break;
1863
1798
      case 's':                 /* --seckey */
1864
1799
        seckey = arg;
1996
1931
    }
1997
1932
  }
1998
1933
  
1999
 
  /* Remove empty interface names */
2000
 
  {
2001
 
    char *interface = NULL;
2002
 
    while((interface = argz_next(interfaces, interfaces_size,
2003
 
                                 interface))){
2004
 
      if(if_nametoindex(interface) == 0){
2005
 
        if(interface[0] != '\0' and strcmp(interface, "none") != 0){
2006
 
          fprintf_plus(stderr, "Not using nonexisting interface"
2007
 
                       " \"%s\"\n", interface);
2008
 
        }
2009
 
        argz_delete(&interfaces, &interfaces_size, interface);
2010
 
        interface = NULL;
2011
 
      }
2012
 
    }
2013
 
  }
2014
 
  
2015
1934
  /* Run network hooks */
2016
 
  {
2017
 
    ret_errno = argz_append(&interfaces_hooks, &interfaces_hooks_size,
2018
 
                            interfaces, interfaces_size);
2019
 
    if(ret_errno != 0){
2020
 
      errno = ret_errno;
2021
 
      perror_plus("argz_append");
2022
 
      goto end;
2023
 
    }
2024
 
    argz_stringify(interfaces_hooks, interfaces_hooks_size, (int)',');
2025
 
    if(not run_network_hooks("start", interfaces_hooks, delay)){
2026
 
      goto end;
2027
 
    }
 
1935
  if(not run_network_hooks("start", interface, delay)){
 
1936
    goto end;
2028
1937
  }
2029
1938
  
2030
1939
  if(not debug){
2031
1940
    avahi_set_log_function(empty_log);
2032
1941
  }
2033
1942
  
 
1943
  if(interface[0] == '\0'){
 
1944
    struct dirent **direntries;
 
1945
    /* First look for interfaces that are up */
 
1946
    ret = scandir(sys_class_net, &direntries, up_interface,
 
1947
                  alphasort);
 
1948
    if(ret == 0){
 
1949
      /* No up interfaces, look for any good interfaces */
 
1950
      free(direntries);
 
1951
      ret = scandir(sys_class_net, &direntries, good_interface,
 
1952
                    alphasort);
 
1953
    }
 
1954
    if(ret >= 1){
 
1955
      /* Pick the first interface returned */
 
1956
      interface = strdup(direntries[0]->d_name);
 
1957
      if(debug){
 
1958
        fprintf_plus(stderr, "Using interface \"%s\"\n", interface);
 
1959
      }
 
1960
      if(interface == NULL){
 
1961
        perror_plus("malloc");
 
1962
        free(direntries);
 
1963
        exitcode = EXIT_FAILURE;
 
1964
        goto end;
 
1965
      }
 
1966
      free(direntries);
 
1967
    } else {
 
1968
      free(direntries);
 
1969
      fprintf_plus(stderr, "Could not find a network interface\n");
 
1970
      exitcode = EXIT_FAILURE;
 
1971
      goto end;
 
1972
    }
 
1973
  }
 
1974
  
2034
1975
  /* Initialize Avahi early so avahi_simple_poll_quit() can be called
2035
1976
     from the signal handler */
2036
1977
  /* Initialize the pseudo-RNG for Avahi */
2106
2047
    }
2107
2048
  }
2108
2049
  
2109
 
  /* If no interfaces were specified, make a list */
2110
 
  if(interfaces == NULL){
2111
 
    struct dirent **direntries;
2112
 
    /* Look for any good interfaces */
2113
 
    ret = scandir(sys_class_net, &direntries, good_interface,
2114
 
                  alphasort);
2115
 
    if(ret >= 1){
2116
 
      /* Add all found interfaces to interfaces list */
2117
 
      for(int i = 0; i < ret; ++i){
2118
 
        ret_errno = argz_add(&interfaces, &interfaces_size,
2119
 
                             direntries[i]->d_name);
2120
 
        if(ret_errno != 0){
2121
 
          perror_plus("argz_add");
2122
 
          continue;
2123
 
        }
2124
 
        if(debug){
2125
 
          fprintf_plus(stderr, "Will use interface \"%s\"\n",
2126
 
                       direntries[i]->d_name);
2127
 
        }
2128
 
      }
2129
 
      free(direntries);
2130
 
    } else {
2131
 
      free(direntries);
2132
 
      fprintf_plus(stderr, "Could not find a network interface\n");
2133
 
      exitcode = EXIT_FAILURE;
2134
 
      goto end;
2135
 
    }
2136
 
  }
2137
 
  
2138
 
  /* If we only got one interface, explicitly use only that one */
2139
 
  if(argz_count(interfaces, interfaces_size) == 1){
2140
 
    if(debug){
2141
 
      fprintf_plus(stderr, "Using only interface \"%s\"\n",
2142
 
                   interfaces);
2143
 
    }
2144
 
    if_index = (AvahiIfIndex)if_nametoindex(interfaces);
2145
 
  }
2146
 
  
2147
 
  /* Bring up interfaces which are down */
2148
 
  if(not (argz_count(interfaces, interfaces_size) == 1
2149
 
          and strcmp(interfaces, "none") == 0)){
2150
 
    char *interface = NULL;
2151
 
    while((interface = argz_next(interfaces, interfaces_size,
2152
 
                                 interface))){
2153
 
      bool interface_was_up = interface_is_up(interface);
2154
 
      ret = bring_up_interface(interface, delay);
2155
 
      if(not interface_was_up){
2156
 
        if(ret != 0){
2157
 
          errno = ret;
2158
 
          perror_plus("Failed to bring up interface");
2159
 
        } else {
2160
 
          ret_errno = argz_add(&interfaces_to_take_down,
2161
 
                               &interfaces_to_take_down_size,
2162
 
                               interface);
2163
 
        }
2164
 
      }
2165
 
    }
2166
 
    free(interfaces);
2167
 
    interfaces = NULL;
2168
 
    interfaces_size = 0;
2169
 
    if(debug and (interfaces_to_take_down == NULL)){
2170
 
      fprintf_plus(stderr, "No interfaces were brought up\n");
 
2050
  /* If the interface is down, bring it up */
 
2051
  if((interface[0] != '\0') and (strcmp(interface, "none") != 0)){
 
2052
    ret = bring_up_interface(interface, delay);
 
2053
    if(ret != 0){
 
2054
      errno = ret;
 
2055
      perror_plus("Failed to bring up interface");
2171
2056
    }
2172
2057
  }
2173
2058
  
2295
2180
    /* Allocate a new server */
2296
2181
    mc.server = avahi_server_new(avahi_simple_poll_get
2297
2182
                                 (mc.simple_poll), &config, NULL,
2298
 
                                 NULL, &ret_errno);
 
2183
                                 NULL, &error);
2299
2184
    
2300
2185
    /* Free the Avahi configuration data */
2301
2186
    avahi_server_config_free(&config);
2304
2189
  /* Check if creating the Avahi server object succeeded */
2305
2190
  if(mc.server == NULL){
2306
2191
    fprintf_plus(stderr, "Failed to create Avahi server: %s\n",
2307
 
                 avahi_strerror(ret_errno));
 
2192
                 avahi_strerror(error));
2308
2193
    exitcode = EX_UNAVAILABLE;
2309
2194
    goto end;
2310
2195
  }
2378
2263
    }
2379
2264
  }
2380
2265
  
 
2266
  /* Run network hooks */
 
2267
  run_network_hooks("stop", interface, delay);
 
2268
  
2381
2269
  /* Re-raise priviliges */
2382
2270
  {
2383
2271
    raise_privileges();
2384
2272
    
2385
 
    /* Run network hooks */
2386
 
    run_network_hooks("stop", interfaces_hooks, delay);
2387
 
    
2388
 
    /* Take down the network interfaces which were brought up */
2389
 
    {
2390
 
      char *interface = NULL;
2391
 
      while((interface=argz_next(interfaces_to_take_down,
2392
 
                                 interfaces_to_take_down_size,
2393
 
                                 interface))){
2394
 
        ret_errno = take_down_interface(interface);
2395
 
        if(ret_errno != 0){
2396
 
          errno = ret_errno;
2397
 
          perror_plus("Failed to take down interface");
 
2273
    /* Take down the network interface */
 
2274
    if(take_down_interface and geteuid() == 0){
 
2275
      ret = ioctl(sd, SIOCGIFFLAGS, &network);
 
2276
      if(ret == -1){
 
2277
        perror_plus("ioctl SIOCGIFFLAGS");
 
2278
      } else if(network.ifr_flags & IFF_UP){
 
2279
        network.ifr_flags &= ~(short)IFF_UP; /* clear flag */
 
2280
        ret = ioctl(sd, SIOCSIFFLAGS, &network);
 
2281
        if(ret == -1){
 
2282
          perror_plus("ioctl SIOCSIFFLAGS -IFF_UP");
2398
2283
        }
2399
2284
      }
2400
 
      if(debug and (interfaces_to_take_down == NULL)){
2401
 
        fprintf_plus(stderr, "No interfaces needed to be taken"
2402
 
                     " down\n");
 
2285
      ret = (int)TEMP_FAILURE_RETRY(close(sd));
 
2286
      if(ret == -1){
 
2287
        perror_plus("close");
2403
2288
      }
2404
2289
    }
2405
 
    
2406
 
    lower_privileges_permanently();
2407
 
  }
2408
 
  
2409
 
  free(interfaces_to_take_down);
2410
 
  free(interfaces_hooks);
 
2290
  }
 
2291
  /* Lower privileges permanently */
 
2292
  errno = 0;
 
2293
  ret = setuid(uid);
 
2294
  if(ret == -1){
 
2295
    perror_plus("setuid");
 
2296
  }
2411
2297
  
2412
2298
  /* Removes the GPGME temp directory and all files inside */
2413
2299
  if(tempdir_created){