gluon-setup-mode: add remote setup-mode
This commit is contained in:
		
							parent
							
								
									1780bafafc
								
							
						
					
					
						commit
						83dbbc182f
					
				@ -35,6 +35,9 @@ init_links := \
 | 
			
		||||
define Package/gluon-setup-mode/install
 | 
			
		||||
	$(Gluon/Build/Install)
 | 
			
		||||
 | 
			
		||||
	$(INSTALL_DIR) $(1)/lib/gluon/setup-mode
 | 
			
		||||
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/wait-network-request $(1)/lib/gluon/setup-mode
 | 
			
		||||
 | 
			
		||||
	$(LN) S20network $(1)/lib/gluon/setup-mode/rc.d/K90network
 | 
			
		||||
 | 
			
		||||
	for link in $(init_links); do \
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,55 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
. /lib/functions.sh
 | 
			
		||||
 | 
			
		||||
device_supports_networked_setup_mode() {
 | 
			
		||||
	local is_networked="$(lua -e 'print(require("gluon.setup-mode").supports_networked_activation())')"
 | 
			
		||||
	
 | 
			
		||||
	if [ "${is_networked}" = "true" ]; then
 | 
			
		||||
		return 0
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
should_activate_networked() {
 | 
			
		||||
	local setup_ifnames="$(lua -e 'print(require("gluon.sysconfig").setup_ifname)')"
 | 
			
		||||
	local should_start=1
 | 
			
		||||
 | 
			
		||||
	if ! device_supports_networked_setup_mode; then
 | 
			
		||||
		return 1
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	for iface in $setup_ifnames
 | 
			
		||||
	do
 | 
			
		||||
		ip link set dev "${iface}" up
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# shellcheck disable=SC2086
 | 
			
		||||
	if /lib/gluon/setup-mode/wait-network-request ${setup_ifnames}; then
 | 
			
		||||
		should_start=0
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	for iface in $setup_ifnames
 | 
			
		||||
	do
 | 
			
		||||
		ip link set dev "${iface}" down
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	return $should_start
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
network_setup_mode_enable() {
 | 
			
		||||
	local enabled="$(uci -q get 'gluon-setup-mode.@setup_mode[0].enabled')"
 | 
			
		||||
	local configured="$(uci -q get 'gluon-setup-mode.@setup_mode[0].configured')"
 | 
			
		||||
 | 
			
		||||
	if [ "$enabled" = 1 ] || [ "$configured" != 1 ]; then
 | 
			
		||||
		return 0
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if should_activate_networked; then
 | 
			
		||||
		uci -q set 'gluon-setup-mode.@setup_mode[0].enabled=1'
 | 
			
		||||
	fi
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
boot_hook_add preinit_main network_setup_mode_enable
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
setup_mode_enable() {
 | 
			
		||||
	local enabled="$(uci -q get 'gluon-setup-mode.@setup_mode[0].enabled')"
 | 
			
		||||
	local configured="$(uci -q get 'gluon-setup-mode.@setup_mode[0].configured')"
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,14 @@
 | 
			
		||||
local platform = require 'gluon.platform'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
local M = {}
 | 
			
		||||
 | 
			
		||||
function M.supports_networked_activation()
 | 
			
		||||
	if platform.match('ramips', 'mt7621', {
 | 
			
		||||
		'zyxel,nwa55axe',
 | 
			
		||||
	}) then
 | 
			
		||||
		return true
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return M
 | 
			
		||||
							
								
								
									
										2
									
								
								package/gluon-setup-mode/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								package/gluon-setup-mode/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
enter-setup-mode
 | 
			
		||||
check-setup-mode
 | 
			
		||||
							
								
								
									
										16
									
								
								package/gluon-setup-mode/src/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								package/gluon-setup-mode/src/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
CC:=gcc
 | 
			
		||||
CFLAGS:=
 | 
			
		||||
LDFLAGS:=
 | 
			
		||||
 | 
			
		||||
all: wait-network-request send-network-request
 | 
			
		||||
 | 
			
		||||
wait-network-request:
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) -o wait-network-request wait-network-request.c
 | 
			
		||||
 | 
			
		||||
send-network-request:
 | 
			
		||||
	$(CC) $(CFLAGS) $(LDFLAGS) -o send-network-request send-network-request.c
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -rf send-network-request wait-network-request
 | 
			
		||||
 | 
			
		||||
.PHONY: clean all
 | 
			
		||||
							
								
								
									
										18
									
								
								package/gluon-setup-mode/src/gluon-remote-setup-mode.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								package/gluon-setup-mode/src/gluon-remote-setup-mode.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
/* Seconds*/
 | 
			
		||||
#define REMOTE_SETUP_MODE_RX_TIMEOUT						5
 | 
			
		||||
#define REMOTE_SETUP_MODE_TX_INTERVAL						1
 | 
			
		||||
 | 
			
		||||
#define REMOTE_SETUP_MODE_MAC_LEN						6
 | 
			
		||||
#define REMOTE_SETUP_MODE_DST_MAC_OFFSET					0
 | 
			
		||||
#define REMOTE_SETUP_MODE_DST_MAC						0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e
 | 
			
		||||
#define REMOTE_SETUP_MODE_SRC_MAC_OFFSET					6
 | 
			
		||||
#define REMOTE_SETUP_MODE_SRC_MAC						0xda, 0xec, 0xe5, 0x8f, 0x60, 0x14
 | 
			
		||||
 | 
			
		||||
#define REMOTE_SETUP_MODE_ETHERTYPE_OFFSET					(REMOTE_SETUP_MODE_MAC_LEN + REMOTE_SETUP_MODE_MAC_LEN)
 | 
			
		||||
#define REMOTE_SETUP_MODE_ETHERTYPE_LEN						2
 | 
			
		||||
#define REMOTE_SETUP_MODE_ETHERTYPE						0x23, 0x42
 | 
			
		||||
 | 
			
		||||
#define REMOTE_SETUP_MODE_DATA_CMD_OFFSET					(REMOTE_SETUP_MODE_ETHERTYPE_OFFSET + REMOTE_SETUP_MODE_ETHERTYPE_LEN)
 | 
			
		||||
#define REMOTE_SETUP_MODE_DATA_CMD_SETUP					"SETUP"
 | 
			
		||||
							
								
								
									
										91
									
								
								package/gluon-setup-mode/src/send-network-request.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								package/gluon-setup-mode/src/send-network-request.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Utility for performing remote setup-mode activation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) David Bauer <mail@david-bauer.net>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <linux/if_packet.h>
 | 
			
		||||
#include <net/ethernet.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
 | 
			
		||||
#include "gluon-remote-setup-mode.h"
 | 
			
		||||
 | 
			
		||||
#define LLDP_DELAY	(REMOTE_SETUP_MODE_TX_INTERVAL * 1000)
 | 
			
		||||
 | 
			
		||||
char buf[] = {
 | 
			
		||||
	/* Destination - LLDP Multicast */
 | 
			
		||||
	REMOTE_SETUP_MODE_DST_MAC,
 | 
			
		||||
	/* Source */
 | 
			
		||||
	REMOTE_SETUP_MODE_SRC_MAC,
 | 
			
		||||
	/* Type */
 | 
			
		||||
	REMOTE_SETUP_MODE_ETHERTYPE,
 | 
			
		||||
	/* Magic*/
 | 
			
		||||
	'S', 'E', 'T', 'U', 'P',
 | 
			
		||||
	/* Trail */
 | 
			
		||||
	0x00,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int get_ifindex(int sock, const char *ifname)
 | 
			
		||||
{
 | 
			
		||||
	struct ifreq ifr;
 | 
			
		||||
 | 
			
		||||
	strncpy((char *)ifr.ifr_name, ifname, IFNAMSIZ);
 | 
			
		||||
 | 
			
		||||
	if (ioctl(sock, SIOCGIFINDEX, &ifr)) {
 | 
			
		||||
		printf("IOCTL error: %s\n", strerror(errno));
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ifr.ifr_ifindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_ll sll;
 | 
			
		||||
	int ifindex;
 | 
			
		||||
	int s_fd;
 | 
			
		||||
 | 
			
		||||
	if (argc < 2 || !strcmp("help", argv[1])) {
 | 
			
		||||
		printf("Usage: %s <ifname>\n", argv[0]);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s_fd = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
 | 
			
		||||
	if (s_fd < 0) {
 | 
			
		||||
		printf("Socket error: %s\n", strerror(errno));
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ifindex = get_ifindex(s_fd, argv[1]);
 | 
			
		||||
	if (ifindex < 0) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	memset(&sll, 0, sizeof(sll));
 | 
			
		||||
	sll.sll_family = AF_PACKET;
 | 
			
		||||
	sll.sll_ifindex = ifindex;
 | 
			
		||||
 | 
			
		||||
	printf("Sending Reset command\n");
 | 
			
		||||
	while (1) {
 | 
			
		||||
		if (sendto(s_fd, buf, sizeof(buf), 0, (struct sockaddr *) &sll, sizeof(sll)) < 0) {
 | 
			
		||||
			printf("Error sending packet: %s\n", strerror(errno));
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		usleep(LLDP_DELAY);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(s_fd);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										154
									
								
								package/gluon-setup-mode/src/wait-network-request.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								package/gluon-setup-mode/src/wait-network-request.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,154 @@
 | 
			
		||||
/* SPDX-License-Identifier: GPL-2.0-only */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Utility for entering Setup_mode using network
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) David Bauer <mail@david-bauer.net>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <linux/if_packet.h>
 | 
			
		||||
#include <net/ethernet.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
 | 
			
		||||
#include "gluon-remote-setup-mode.h"
 | 
			
		||||
 | 
			
		||||
#define MAX_INTERFACES	64
 | 
			
		||||
#define BUFSIZE		1024
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
char destination[]				= { REMOTE_SETUP_MODE_DST_MAC };
 | 
			
		||||
char type[]						= { REMOTE_SETUP_MODE_ETHERTYPE };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int bind_socket_to_device(int fd, int ifindex)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_ll sll = {
 | 
			
		||||
		.sll_family = AF_PACKET,
 | 
			
		||||
		.sll_ifindex = ifindex,
 | 
			
		||||
		.sll_protocol = htons(ETH_P_ALL)
 | 
			
		||||
	}; 
 | 
			
		||||
 | 
			
		||||
	if((bind(fd , (struct sockaddr *)&sll , sizeof(sll))) < 0) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int should_reset(char *buf, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	int should_reset;
 | 
			
		||||
	char *tlv_ptr;
 | 
			
		||||
 | 
			
		||||
	should_reset = 0;
 | 
			
		||||
 | 
			
		||||
	if (size < REMOTE_SETUP_MODE_DATA_CMD_OFFSET + strlen(REMOTE_SETUP_MODE_DATA_CMD_SETUP) + 1) {
 | 
			
		||||
		/* Length mismatch */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (buf[size - 1] != 0x00) {
 | 
			
		||||
		/* Wrong trailer */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (memcmp(destination, &buf[REMOTE_SETUP_MODE_DST_MAC_OFFSET], sizeof(destination))) {
 | 
			
		||||
		/* Wrong destination-etheraddr */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (memcmp(type, &buf[REMOTE_SETUP_MODE_ETHERTYPE_OFFSET], sizeof(type))) {
 | 
			
		||||
		/* Wrong Ethertype */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(&buf[REMOTE_SETUP_MODE_DATA_CMD_OFFSET], REMOTE_SETUP_MODE_DATA_CMD_SETUP)) {
 | 
			
		||||
		/* Wrong Command */
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	time_t start_time, current_time;
 | 
			
		||||
	int ifindex[MAX_INTERFACES];
 | 
			
		||||
	int sockets[MAX_INTERFACES];
 | 
			
		||||
	char recvbuf[BUFSIZE];
 | 
			
		||||
	int num_interfaces;
 | 
			
		||||
	int received;
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	start_time = time(NULL);
 | 
			
		||||
 | 
			
		||||
	if (argc < 2) {
 | 
			
		||||
		fprintf(stderr, "At least one Interface name is required\n", MAX_INTERFACES);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (argc > MAX_INTERFACES) {
 | 
			
		||||
		fprintf(stderr, "Exceeded maximum number of supported interfaces of %d\n", MAX_INTERFACES);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	num_interfaces = 0;
 | 
			
		||||
	for (i = 1; i < argc; i++) {
 | 
			
		||||
		ifindex[num_interfaces] = if_nametoindex(argv[i]);
 | 
			
		||||
		if (!ifindex[num_interfaces]) {
 | 
			
		||||
			fprintf(stderr, "Interface %s not found!\n", argv[i]);
 | 
			
		||||
		}
 | 
			
		||||
		num_interfaces++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_interfaces; i++) {
 | 
			
		||||
		sockets[i] = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
 | 
			
		||||
		if (sockets[i] < 0) {
 | 
			
		||||
			fprintf(stderr, "Could not create socket for ifindex %d\n", ifindex[i]);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (bind_socket_to_device(sockets[i], ifindex[i])) {
 | 
			
		||||
			fprintf(stderr, "Error binding socket to Interface %d\n", ifindex[i]);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Start receiving */
 | 
			
		||||
	while (1) {
 | 
			
		||||
		/* Check if timeout is exceeded */
 | 
			
		||||
		current_time = time(NULL);
 | 
			
		||||
		if (current_time - start_time > REMOTE_SETUP_MODE_RX_TIMEOUT) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < num_interfaces; i++) {
 | 
			
		||||
			received = recv(sockets[i], recvbuf, BUFSIZE, MSG_DONTWAIT);
 | 
			
		||||
			if (received < 0 && errno != EAGAIN && errno != EAGAIN) {
 | 
			
		||||
				fprintf(stderr, "Error receiving from ifindex %d - ret %d\n", ifindex[i], errno);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (received <= 0) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (!should_reset(recvbuf, received)) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user