42
42
#include <stdio.h> /* fprintf(), stderr, fwrite(),
43
43
stdout, ferror(), remove() */
44
#include <stdint.h> /* uint16_t, uint32_t */
44
#include <stdint.h> /* uint16_t, uint32_t, intptr_t */
45
45
#include <stddef.h> /* NULL, size_t, ssize_t */
46
46
#include <stdlib.h> /* free(), EXIT_SUCCESS, srand(),
47
47
strtof(), abort() */
824
/* Spurious warning from -Wint-to-pointer-cast */
825
gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) tcp_sd);
826
/* This casting via intptr_t is to eliminate warning about casting
827
an int to a pointer type. This is exactly how the GnuTLS Guile
828
function "set-session-transport-fd!" does it. */
829
gnutls_transport_set_ptr(session,
830
(gnutls_transport_ptr_t)(intptr_t)tcp_sd);
1395
/* Set effective uid to 0, return errno */
1396
int raise_privileges(void){
1397
int old_errno = errno;
1400
if(seteuid(0) == -1){
1401
perror_plus("seteuid");
1408
/* Set effective and real user ID to 0. Return errno. */
1409
int raise_privileges_permanently(void){
1410
int old_errno = errno;
1411
int ret_errno = raise_privileges();
1417
if(setuid(0) == -1){
1418
perror_plus("seteuid");
1425
/* Set effective user ID to unprivileged saved user ID */
1426
int lower_privileges(void){
1427
int old_errno = errno;
1430
if(seteuid(uid) == -1){
1431
perror_plus("seteuid");
1390
1438
bool run_network_hooks(const char *mode, const char *interface,
1391
1439
const float delay){
1392
1440
struct dirent **direntries;
1564
int bring_up_interface(const char * const interface, const float delay){
1566
int old_errno = errno;
1569
struct ifreq network;
1570
AvahiIfIndex if_index = (AvahiIfIndex)if_nametoindex(interface);
1572
fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
1582
/* Re-raise priviliges */
1586
/* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
1587
messages about the network interface to mess up the prompt */
1588
ret = klogctl(8, NULL, 5);
1589
bool restore_loglevel = true;
1591
restore_loglevel = false;
1592
perror_plus("klogctl");
1594
#endif /* __linux__ */
1596
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1599
perror_plus("socket");
1601
if(restore_loglevel){
1602
ret = klogctl(7, NULL, 0);
1604
perror_plus("klogctl");
1607
#endif /* __linux__ */
1608
/* Lower privileges */
1613
strcpy(network.ifr_name, interface);
1614
ret = ioctl(sd, SIOCGIFFLAGS, &network);
1617
perror_plus("ioctl SIOCGIFFLAGS");
1619
if(restore_loglevel){
1620
ret = klogctl(7, NULL, 0);
1622
perror_plus("klogctl");
1625
#endif /* __linux__ */
1626
/* Lower privileges */
1631
if((network.ifr_flags & IFF_UP) == 0){
1632
network.ifr_flags |= IFF_UP;
1633
ret = ioctl(sd, SIOCSIFFLAGS, &network);
1636
perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
1638
if(restore_loglevel){
1639
ret = klogctl(7, NULL, 0);
1641
perror_plus("klogctl");
1644
#endif /* __linux__ */
1645
/* Lower privileges */
1651
/* Sleep checking until interface is running.
1652
Check every 0.25s, up to total time of delay */
1653
for(int i=0; i < delay * 4; i++){
1654
ret = ioctl(sd, SIOCGIFFLAGS, &network);
1656
perror_plus("ioctl SIOCGIFFLAGS");
1657
} else if(network.ifr_flags & IFF_RUNNING){
1660
struct timespec sleeptime = { .tv_nsec = 250000000 };
1661
ret = nanosleep(&sleeptime, NULL);
1662
if(ret == -1 and errno != EINTR){
1663
perror_plus("nanosleep");
1666
/* Close the socket */
1667
ret = (int)TEMP_FAILURE_RETRY(close(sd));
1669
perror_plus("close");
1672
if(restore_loglevel){
1673
/* Restores kernel loglevel to default */
1674
ret = klogctl(7, NULL, 0);
1676
perror_plus("klogctl");
1679
#endif /* __linux__ */
1680
/* Lower privileges */
1526
1686
int main(int argc, char *argv[]){
1527
1687
AvahiSServiceBrowser *sb = NULL;
1898
2052
/* If the interface is down, bring it up */
1899
if(strcmp(interface, "none") != 0){
1900
if_index = (AvahiIfIndex) if_nametoindex(interface);
1902
fprintf_plus(stderr, "No such interface: \"%s\"\n", interface);
1903
exitcode = EX_UNAVAILABLE;
1911
/* Re-raise priviliges */
1915
perror_plus("seteuid");
1919
/* Lower kernel loglevel to KERN_NOTICE to avoid KERN_INFO
1920
messages about the network interface to mess up the prompt */
1921
ret = klogctl(8, NULL, 5);
1922
bool restore_loglevel = true;
1924
restore_loglevel = false;
1925
perror_plus("klogctl");
1927
#endif /* __linux__ */
1929
sd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
1931
perror_plus("socket");
1932
exitcode = EX_OSERR;
1934
if(restore_loglevel){
1935
ret = klogctl(7, NULL, 0);
1937
perror_plus("klogctl");
1940
#endif /* __linux__ */
1941
/* Lower privileges */
1945
perror_plus("seteuid");
1949
strcpy(network.ifr_name, interface);
1950
ret = ioctl(sd, SIOCGIFFLAGS, &network);
1952
perror_plus("ioctl SIOCGIFFLAGS");
1954
if(restore_loglevel){
1955
ret = klogctl(7, NULL, 0);
1957
perror_plus("klogctl");
1960
#endif /* __linux__ */
1961
exitcode = EX_OSERR;
1962
/* Lower privileges */
1966
perror_plus("seteuid");
1970
if((network.ifr_flags & IFF_UP) == 0){
1971
network.ifr_flags |= IFF_UP;
1972
take_down_interface = true;
1973
ret = ioctl(sd, SIOCSIFFLAGS, &network);
1975
take_down_interface = false;
1976
perror_plus("ioctl SIOCSIFFLAGS +IFF_UP");
1977
exitcode = EX_OSERR;
1979
if(restore_loglevel){
1980
ret = klogctl(7, NULL, 0);
1982
perror_plus("klogctl");
1985
#endif /* __linux__ */
1986
/* Lower privileges */
1990
perror_plus("seteuid");
1995
/* Sleep checking until interface is running.
1996
Check every 0.25s, up to total time of delay */
1997
for(int i=0; i < delay * 4; i++){
1998
ret = ioctl(sd, SIOCGIFFLAGS, &network);
2000
perror_plus("ioctl SIOCGIFFLAGS");
2001
} else if(network.ifr_flags & IFF_RUNNING){
2004
struct timespec sleeptime = { .tv_nsec = 250000000 };
2005
ret = nanosleep(&sleeptime, NULL);
2006
if(ret == -1 and errno != EINTR){
2007
perror_plus("nanosleep");
2010
if(not take_down_interface){
2011
/* We won't need the socket anymore */
2012
ret = (int)TEMP_FAILURE_RETRY(close(sd));
2014
perror_plus("close");
2018
if(restore_loglevel){
2019
/* Restores kernel loglevel to default */
2020
ret = klogctl(7, NULL, 0);
2022
perror_plus("klogctl");
2025
#endif /* __linux__ */
2026
/* Lower privileges */
2028
/* Lower privileges */
2031
perror_plus("seteuid");
2053
if((interface[0] != '\0') and (strcmp(interface, "none") != 0)){
2054
ret = bring_up_interface(interface, delay);
2057
perror_plus("Failed to bring up interface");