Exemple #1
0
int ctrl_iface_systemd_socket()
{
	char *env, *ptr;
	unsigned int p, l;

	env = getenv("LISTEN_PID");
	if (!env)
		return -1;

	p = strtoul(env, &ptr, 10);
	if (ptr && ptr == env) {
		LLDPAD_DBG("Invalid value '%s' for LISTEN_PID\n", env);
		return -1;
	}
	if ((pid_t)p != getpid()) {
		LLDPAD_DBG("Invalid PID '%d' from LISTEN_PID\n", p);
		return -1;
	}
	env = getenv("LISTEN_FDS");
	if (!env) {
		LLDPAD_DBG("LISTEN_FDS is not set\n");
		return -1;
	}
	l = strtoul(env, &ptr, 10);
	if (ptr && ptr == env) {
		LLDPAD_INFO("Invalid value '%s' for LISTEN_FDS\n", env);
		return -1;
	}
	if (l != 1) {
		LLDPAD_INFO("LISTEN_FDS specified %d fds\n", l);
		return -1;
	}
	/* systemd returns fds with an offset of '3' */
	return 3;
}
Exemple #2
0
int ctrl_iface_init(struct clif_data *clifd)
{
	struct sockaddr_un addr;
	int s = -1;
	socklen_t addrlen;
	const int feature_on = 1;

	clifd->ctrl_sock = -1;
	clifd->ctrl_dst = NULL;

	s = ctrl_iface_systemd_socket();
	if (s != -1) {
		LLDPAD_INFO("using fd %d from systemd\n", s);
		goto out;
	}
	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
	if (s < 0) {
		LLDPAD_WARN("failed to create CLI socket: %m\n");
		goto fail;
	}
	/* enable receiving of the sender credentials */
	setsockopt(s, SOL_SOCKET, SO_PASSCRED,
		   &feature_on, sizeof(feature_on));

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_LOCAL;
	snprintf(&addr.sun_path[1], sizeof(addr.sun_path) - 1,
		 "%s", LLDP_CLIF_SOCK);
	addrlen = sizeof(sa_family_t) + strlen(addr.sun_path + 1) + 1;
	if (bind(s, (struct sockaddr *) &addr, addrlen) < 0) {
		if (errno == EADDRINUSE)
			LLDPAD_WARN("another lldpad instance is running\n");
		else
			LLDPAD_WARN("failed to bind CLI socket address: %m");
		goto fail;
	}
	/* enable receiving of the sender credentials */
	setsockopt(s, SOL_SOCKET, SO_PASSCRED,
		   &feature_on, sizeof(feature_on));

	LLDPAD_INFO("bound ctrl iface to %s\n", &addr.sun_path[1]);
out:
	clifd->ctrl_sock = s;

	return 0;

fail:
	if (s >= 0)
		close(s);
	return -1;
}
Exemple #3
0
static void l2_packet_receive(int sock, void *eloop_ctx, UNUSED void *sock_ctx)
{
	struct l2_packet_data *l2 = eloop_ctx;
	u8 buf[2300];
	int res;
	struct sockaddr_ll ll;
	socklen_t fromlen;

	memset(&ll, 0, sizeof(ll));
	fromlen = sizeof(ll);
	res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
		       &fromlen);

	if (res < 0) {
		LLDPAD_INFO("receive if %s ERROR = %d\n", l2->ifname, errno);
		if (errno != ENETDOWN)
			perror("l2_packet_receive - recvfrom");
		return;
	}

	l2->rx_callback(l2->rx_callback_ctx, ll.sll_ifindex, buf, res);
}
Exemple #4
0
static void ctrl_iface_receive(int sock, void *eloop_ctx,
			       UNUSED void *sock_ctx)
{
	struct clif_data *clifd = eloop_ctx;
	char buf[MAX_CLIF_MSGBUF];
	struct msghdr smsg;
	struct cmsghdr *cmsg;
	struct iovec iov;
	struct ucred *cred;
	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
	int res;
	struct sockaddr_un from;
	socklen_t fromlen = sizeof(from);
	char *reply;
	const int reply_size = MAX_CLIF_MSGBUF;
	int reply_len;

	memset(&buf, 0x00, sizeof(buf));
	iov.iov_base = buf;
	iov.iov_len = sizeof(buf) - 1;

	memset(&smsg, 0x00, sizeof(struct msghdr));
	smsg.msg_name = &from;
	smsg.msg_namelen = fromlen;
	smsg.msg_iov = &iov;
	smsg.msg_iovlen = 1;
	smsg.msg_control = cred_msg;
	smsg.msg_controllen = sizeof(cred_msg);

	res = recvmsg(sock, &smsg, 0);
	if (res < 0) {
		perror("recvfrom(ctrl_iface)");
		return;
	}
	cmsg = CMSG_FIRSTHDR(&smsg);
	fromlen = smsg.msg_namelen;
	cred = (struct ucred *)CMSG_DATA(cmsg);

	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
		LLDPAD_INFO("%s: No sender credentials, ignoring\n",
			   __FUNCTION__);
		sprintf(buf,"R%02x", cmd_bad_params);
		sendto(sock, buf, 3, 0, (struct sockaddr *) &from, fromlen);
		return;
	}
	if (cred->uid != 0) {
		LLDPAD_INFO("%s: sender uid=%i, ignoring\n",
			   __FUNCTION__, cred->uid);
		sprintf(buf,"R%02x", cmd_no_access);
		sendto(sock, buf, 3, 0, (struct sockaddr *) &from,
			fromlen);
		return;
	}

	buf[res] = '\0';
	/* wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res); */

	reply = malloc(reply_size);
	if (reply == NULL) {
		sendto(sock, "R01", 3, 0, (struct sockaddr *) &from,
		       fromlen);
		return;
	}

	memset(reply, 0, reply_size);
	process_clif_cmd(clifd, &from, fromlen, buf, res,
			 reply, reply_size, &reply_len);

	/* wpa_hexdump_ascii(MSG_DEBUG, "TX ctrl_iface", (u8 *) reply, reply_len); */
	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
	free(reply);
}
Exemple #5
0
struct l2_packet_data * l2_packet_init(
	const char *ifname, UNUSED const u8 *own_addr, unsigned short protocol,
	void (*rx_callback)(void *ctx, int ifindex,
			    const u8 *buf, size_t len),
	void *rx_callback_ctx, int l2_hdr)
{
	struct l2_packet_data *l2;
	struct ifreq ifr;
	struct sockaddr_ll ll;

	l2 = malloc(sizeof(struct l2_packet_data));
	if (l2 == NULL)
		return NULL;
	memset(l2, 0, sizeof(*l2));
	strncpy(l2->ifname, ifname, sizeof(l2->ifname));
	l2->rx_callback = rx_callback;
	l2->rx_callback_ctx = rx_callback_ctx;
	l2->l2_hdr = l2_hdr;

	l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
			htons(protocol));

	if (l2->fd < 0) {
		perror("socket(PF_PACKET)");
		free(l2);
		return NULL;
	}

	strncpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
	if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
		perror("ioctl[SIOCGIFINDEX]");
		close(l2->fd);
		free(l2);
		return NULL;
	}
	l2->ifindex = ifr.ifr_ifindex;

	memset(&ll, 0, sizeof(ll));
	ll.sll_family = PF_PACKET;
	ll.sll_ifindex = ifr.ifr_ifindex;
	ll.sll_protocol = htons(protocol);
	if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
		perror("bind[PF_PACKET]");
		close(l2->fd);
		free(l2);
		return NULL;
	}

	/* current hw address */
	if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) {
		perror("ioctl[SIOCGIFHWADDR]");
		close(l2->fd);
		free(l2);
		return NULL;
	}
	memcpy(l2->curr_mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);

	if (get_perm_hwaddr(ifname, l2->perm_mac_addr, l2->san_mac_addr) != 0) {
		memcpy(l2->perm_mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
		memset(l2->san_mac_addr, 0xff, ETH_ALEN);
	}
	LLDPAD_DBG("%s mac:" MACSTR " perm:" MACSTR " san:" MACSTR "\n",
		   ifname, MAC2STR(l2->curr_mac_addr),
		   MAC2STR(l2->perm_mac_addr), MAC2STR(l2->san_mac_addr));

	struct packet_mreq mr;
	memset(&mr, 0, sizeof(mr));
	mr.mr_ifindex = l2->ifindex;
	mr.mr_alen = ETH_ALEN;
	memcpy(mr.mr_address, &nearest_bridge, ETH_ALEN);
	mr.mr_type = PACKET_MR_MULTICAST;
	if (setsockopt(l2->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
		sizeof(mr)) < 0) {
		perror("setsockopt nearest_bridge");
		close(l2->fd);
		free(l2);
		return NULL;
	}

	memcpy(mr.mr_address, &nearest_customer_bridge, ETH_ALEN);
	if (setsockopt(l2->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
		       sizeof(mr)) < 0)
		perror("setsockopt nearest_customer_bridge");

	memcpy(mr.mr_address, &nearest_nontpmr_bridge, ETH_ALEN);
	if (setsockopt(l2->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
		       sizeof(mr)) < 0)
		perror("setsockopt nearest_nontpmr_bridge");

	int option = 1;
	int option_size = sizeof(option);
	if (setsockopt(l2->fd, SOL_PACKET, PACKET_ORIGDEV,
		&option, option_size) < 0) {
		perror("setsockopt SOL_PACKET");
		close(l2->fd);
		free(l2);
		return NULL;
	}

	option = TC_PRIO_CONTROL;
	if ( setsockopt(l2->fd, SOL_SOCKET, SO_PRIORITY, &option,
		sizeof(option_size)) < 0) {
		perror("setsockopt SOL_PRIORITY");
		close(l2->fd);
		free(l2);
		return NULL;
	}

	LLDPAD_INFO("%s MAC address is " MACSTR "\n",
		ifname, MAC2STR(l2->perm_mac_addr));

	eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);

	return l2;
}