int lldpd_iface_init(struct lldpd *, struct lldpd_hardware *);
int lldpd_iface_init_vlan(struct lldpd *, struct lldpd_vif *);
void lldpd_iface_init_mtu(struct lldpd *, struct lldpd_hardware *);
-int lldpd_iface_init_socket(struct lldpd *, struct lldpd_hardware *);
int lldpd_iface_close(struct lldpd *, struct lldpd_hardware *);
void lldpd_iface_multicast(struct lldpd *, const char *, int);
hardware->h_mtu = ifr.ifr_mtu;
}
-int
-lldpd_iface_init_socket(struct lldpd *global, struct lldpd_hardware *hardware)
-{
- struct sockaddr_ll sa;
-
- /* Open listening socket to receive/send frames */
- if ((hardware->h_raw = socket(PF_PACKET, SOCK_RAW,
- htons(ETH_P_ALL))) < 0)
- return errno;
- memset(&sa, 0, sizeof(sa));
- sa.sll_family = AF_PACKET;
- sa.sll_protocol = 0;
- sa.sll_ifindex = if_nametoindex(hardware->h_ifname);
- if (bind(hardware->h_raw, (struct sockaddr*)&sa, sizeof(sa)) < 0)
- return errno;
-
- return 0;
-}
-
int
lldpd_iface_init_vlan(struct lldpd *global, struct lldpd_vif *vif)
{
short int filter;
lldpd_iface_init_mtu(global, (struct lldpd_hardware*)vif);
- status = lldpd_iface_init_socket(global, (struct lldpd_hardware*)vif);
+ status = priv_iface_init((struct lldpd_hardware*)vif, -1);
if (status != 0)
return status;
int
lldpd_iface_init(struct lldpd *global, struct lldpd_hardware *hardware)
{
- struct sockaddr_ll sa;
int master; /* Bond device */
char if_bond[IFNAMSIZ];
- int un = 1;
int status;
short int filter;
lldpd_iface_init_mtu(global, hardware);
- status = lldpd_iface_init_socket(global, hardware);
+ status = priv_iface_init(hardware, -1);
if (status != 0)
return status;
hardware->h_raw_real = hardware->h_raw;
hardware->h_master = master;
hardware->h_raw = -1;
- if ((hardware->h_raw = socket(PF_PACKET, SOCK_RAW,
- htons(ETH_P_ALL))) < 0)
- return errno;
- memset(&sa, 0, sizeof(sa));
- sa.sll_family = AF_PACKET;
- sa.sll_protocol = 0;
- sa.sll_ifindex = master;
- if (bind(hardware->h_raw, (struct sockaddr*)&sa,
- sizeof(sa)) < 0)
- return errno;
- /* With bonding, we need to listen to bond device. We use
- * setsockopt() PACKET_ORIGDEV to get physical device instead of
- * bond device */
- if (setsockopt(hardware->h_raw, SOL_PACKET,
- PACKET_ORIGDEV, &un, sizeof(un)) == -1) {
- LLOG_WARN("unable to setsockopt for master bonding device of %s. "
- "You will get inaccurate results",
- hardware->h_ifname);
- }
+ status = priv_iface_init(hardware, master);
+ if (status != 0) {
+ close(hardware->h_raw_real);
+ if (hardware->h_raw != -1)
+ close(hardware->h_raw);
+ return status;
+ }
}
if (global->g_multi)
void
lldpd_iface_multicast(struct lldpd *global, const char *name, int remove)
{
- struct ifreq ifr;
- int i;
-
+ int i, rc;
+
for (i=0; global->g_protocols[i].mode != 0; i++) {
if (!global->g_protocols[i].enabled) continue;
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
- memcpy(ifr.ifr_hwaddr.sa_data,
- global->g_protocols[i].mac, ETH_ALEN);
- if (ioctl(global->g_sock, (remove)?SIOCDELMULTI:SIOCADDMULTI,
- &ifr) < 0) {
- if (errno == ENOENT)
- return;
- LLOG_INFO("unable to %s %s address to multicast filter for %s",
- (remove)?"delete":"add",
- global->g_protocols[i].name,
- name);
+ if ((rc = priv_iface_multicast(name,
+ global->g_protocols[i].mac, !remove)) != 0) {
+ errno = rc;
+ if (errno != ENOENT)
+ LLOG_INFO("unable to %s %s address to multicast filter for %s",
+ (remove)?"delete":"add",
+ global->g_protocols[i].name,
+ name);
}
}
}
#include <sys/ioctl.h>
#include <netdb.h>
#include <linux/sockios.h>
+#include <netpacket/packet.h>
enum {
PRIV_FORK,
PRIV_GET_HOSTNAME,
PRIV_OPEN,
PRIV_ETHTOOL,
+ PRIV_IFACE_INIT,
+ PRIV_IFACE_MULTICAST,
};
static int may_read(int, void *, size_t);
int remote; /* Other side */
int monitored = -1; /* Child */
+int sock = -1;
/* Proxies */
return rc;
}
+int
+priv_iface_init(struct lldpd_hardware *hardware, int master)
+{
+ 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_read(remote, &rc, sizeof(int));
+ if (rc != 0)
+ return rc; /* It's errno */
+ hardware->h_raw = receive_fd(remote);
+ return 0;
+}
+
+int
+priv_iface_multicast(char *name, u_int8_t *mac, int add)
+{
+ int cmd, rc;
+ cmd = PRIV_IFACE_MULTICAST;
+ must_write(remote, &cmd, sizeof(cmd));
+ must_write(remote, name, IFNAMSIZ);
+ must_write(remote, mac, ETH_ALEN);
+ must_write(remote, &add, sizeof(int));
+ must_read(remote, &rc, sizeof(int));
+ return rc;
+}
+
void
asroot_fork()
{
{
struct ifreq ifr;
struct ethtool_cmd ethc;
- int len, rc, sock;
+ int len, rc;
char *ifname;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
ifr.ifr_data = (caddr_t)ðc;
ethc.cmd = ETHTOOL_GSET;
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- LLOG_WARN("[priv]: unable to get a socket");
- must_write(remote, &sock, sizeof(int));
- free(ifname);
- return;
- }
if ((rc = ioctl(sock, SIOCETHTOOL, &ifr)) != 0) {
LLOG_WARN("[priv]: unable to ioctl ETHTOOL for %s", ifname);
must_write(remote, &rc, sizeof(int));
close(sock);
return;
}
- close(sock);
must_write(remote, &rc, sizeof(int));
must_write(remote, ðc, sizeof(struct ethtool_cmd));
}
+void
+asroot_iface_init()
+{
+ struct sockaddr_ll sa;
+ int un = 1;
+ int s, master;
+ char ifname[IFNAMSIZ];
+
+ must_read(remote, &master, sizeof(int));
+ must_read(remote, ifname, IFNAMSIZ);
+
+ /* Open listening socket to receive/send frames */
+ if ((s = socket(PF_PACKET, SOCK_RAW,
+ htons(ETH_P_ALL))) < 0) {
+ must_write(remote, &errno, sizeof(errno));
+ return;
+ }
+ 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;
+ 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
+asroot_iface_multicast()
+{
+ int add, rc = 0;
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ must_read(remote, ifr.ifr_name, IFNAMSIZ);
+ must_read(remote, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+ must_read(remote, &add, sizeof(int));
+
+ if (ioctl(sock, (add)?SIOCADDMULTI:SIOCDELMULTI,
+ &ifr) < 0) {
+ must_write(remote, &errno, sizeof(errno));
+ return;
+ }
+
+ must_write(remote, &rc, sizeof(rc));
+}
+
struct dispatch_actions {
int msg;
void(*function)(void);
{PRIV_GET_HOSTNAME, asroot_gethostbyname},
{PRIV_OPEN, asroot_open},
{PRIV_ETHTOOL, asroot_ethtool},
+ {PRIV_IFACE_INIT, asroot_iface_init},
+ {PRIV_IFACE_MULTICAST, asroot_iface_multicast},
{-1, NULL}
};
close(pair[0]);
if (atexit(priv_exit) != 0)
fatal("[priv]: unable to set exit function");
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ fatal("[priv]: unable to get a socket");
+ }
signal(SIGALRM, sig_pass_to_chld);
signal(SIGTERM, sig_pass_to_chld);