#include <stdio.h>
#include <unistd.h>
#include <errno.h>
-#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
-#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <regex.h>
#include <linux/sockios.h>
#include <linux/if_packet.h>
+/* Use resolv.h */
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h> /* DNS HEADER struct */
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#include <resolv.h>
+
enum {
PRIV_PING,
PRIV_CREATE_CTL_SOCKET,
static int may_read(int, void *, size_t);
static void must_read(int, void *, size_t);
-static void must_write(int, void *, size_t);
+static void must_write(int, const void *, size_t);
-int remote; /* Other side */
-int monitored = -1; /* Child */
-int sock = -1;
+static int remote; /* Other side */
+static int monitored = -1; /* Child */
+static int sock = -1;
/* UID/GID of unprivileged user */
-gid_t gid = 0;
-uid_t uid = 0;
+static gid_t gid = 0;
+static uid_t uid = 0;
/* Proxies */
-void
+static void
priv_ping()
{
int cmd, rc;
}
int
-priv_iface_init(struct lldpd_hardware *hardware, int master)
+priv_iface_init(const char *name)
{
int cmd, rc;
cmd = PRIV_IFACE_INIT;
must_write(remote, &cmd, sizeof(int));
- must_write(remote, &master, sizeof(int));
- must_write(remote, hardware->h_ifname, IFNAMSIZ);
+ must_write(remote, name, IFNAMSIZ);
must_read(remote, &rc, sizeof(int));
- if (rc != 0)
- return rc; /* It's errno */
- hardware->h_raw = receive_fd(remote);
- return 0;
+ if (rc != 0) return -1;
+ return receive_fd(remote);
}
int
-priv_iface_multicast(char *name, u_int8_t *mac, int add)
+priv_iface_multicast(const char *name, u_int8_t *mac, int add)
{
int cmd, rc;
cmd = PRIV_IFACE_MULTICAST;
return receive_fd(remote);
}
-void
+static void
asroot_ping()
{
int rc = 1;
must_write(remote, &rc, sizeof(int));
}
-void
+static void
asroot_ctl_create()
{
int rc;
close(rc);
}
-void
+static void
asroot_ctl_cleanup()
{
int rc = 0;
must_write(remote, &rc, sizeof(int));
}
-void
+static void
asroot_gethostbyname()
{
struct utsname un;
int len;
if (uname(&un) != 0)
fatal("[priv]: failed to get system information");
- if ((hp = gethostbyname(un.nodename)) == NULL)
- fatal("[priv]: failed to get system name");
- len = strlen(hp->h_name);
- must_write(remote, &len, sizeof(int));
- must_write(remote, hp->h_name, strlen(hp->h_name) + 1);
+ if ((hp = gethostbyname(un.nodename)) == NULL) {
+ LLOG_INFO("[priv]: unable to get system name");
+ res_init();
+ len = strlen(un.nodename);
+ must_write(remote, &len, sizeof(int));
+ must_write(remote, un.nodename, len + 1);
+ } else {
+ len = strlen(hp->h_name);
+ must_write(remote, &len, sizeof(int));
+ must_write(remote, hp->h_name, len + 1);
+ }
}
-void
+static void
asroot_open()
{
const char* authorized[] = {
"/proc/sys/net/ipv4/ip_forward",
- "/sys/class/net/[^.][^/]*/brforward",
- "/sys/class/net/[^.][^/]*/brport",
+ "/proc/net/bonding/[^.][^/]*",
+ "/proc/self/net/bonding/[^.][^/]*",
+ SYSFS_CLASS_NET "[^.][^/]*/brforward",
+ SYSFS_CLASS_NET "[^.][^/]*/brport",
+ SYSFS_CLASS_NET "[^.][^/]*/brif/[^.][^/]*/port_no",
+ SYSFS_CLASS_NET "[^.][^/]*/ifalias",
+ SYSFS_CLASS_DMI "product_version",
+ SYSFS_CLASS_DMI "product_serial",
+ SYSFS_CLASS_DMI "product_name",
+ SYSFS_CLASS_DMI "bios_version",
+ SYSFS_CLASS_DMI "sys_vendor",
+ SYSFS_CLASS_DMI "chassis_asset_tag",
NULL
};
- char **f;
+ const char **f;
char *file;
int fd, len, rc;
regex_t preg;
close(fd);
}
-void
+static void
asroot_ethtool()
{
struct ifreq ifr;
ifr.ifr_data = (caddr_t)ðc;
ethc.cmd = ETHTOOL_GSET;
if ((rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) {
- LLOG_DEBUG("[priv]: unable to ioctl ETHTOOL for %s",
- ifr.ifr_name);
must_write(remote, &rc, sizeof(int));
- close(sock);
return;
}
must_write(remote, &rc, sizeof(int));
must_write(remote, ðc, sizeof(struct ethtool_cmd));
}
-void
+static void
asroot_iface_init()
{
struct sockaddr_ll sa;
- int un = 1;
- int s, master;
+ int s;
char ifname[IFNAMSIZ];
- must_read(remote, &master, sizeof(int));
must_read(remote, ifname, IFNAMSIZ);
ifname[IFNAMSIZ-1] = '\0';
memset(&sa, 0, sizeof(sa));
sa.sll_family = AF_PACKET;
sa.sll_protocol = 0;
- if (master == -1)
- sa.sll_ifindex = if_nametoindex(ifname);
- else
- sa.sll_ifindex = master;
+ sa.sll_ifindex = if_nametoindex(ifname);
if (bind(s, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
must_write(remote, &errno, sizeof(errno));
close(s);
return;
}
-
- if (master != -1) {
- /* With bonding, we need to listen to bond device. We use
- * setsockopt() PACKET_ORIGDEV to get physical device instead of
- * bond device */
- if (setsockopt(s, SOL_PACKET,
- PACKET_ORIGDEV, &un, sizeof(un)) == -1) {
- LLOG_WARN("[priv]: unable to setsockopt for master bonding device of %s. "
- "You will get inaccurate results",
- ifname);
- }
- }
errno = 0;
must_write(remote, &errno, sizeof(errno));
send_fd(remote, s);
close(s);
}
-void
+static void
asroot_iface_multicast()
{
int add, rc = 0;
void(*function)(void);
};
-struct dispatch_actions actions[] = {
+static struct dispatch_actions actions[] = {
{PRIV_PING, asroot_ping},
{PRIV_CREATE_CTL_SOCKET, asroot_ctl_create},
{PRIV_DELETE_CTL_SOCKET, asroot_ctl_cleanup},
};
/* Main loop, run as root */
-void
+static void
priv_loop()
{
int cmd;
/* Should never be there */
}
-void
+static void
priv_exit()
{
int status;
/* Write data with the assertion that it all has to be written, or
* else abort the process. Based on atomicio() from openssh. */
static void
-must_write(int fd, void *buf, size_t n)
+must_write(int fd, const void *buf, size_t n)
{
- char *s = buf;
+ const char *s = buf;
ssize_t res, pos = 0;
while (n > pos) {