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
|
define Package/gluon-setup-mode/install
|
||||||
$(Gluon/Build/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
|
$(LN) S20network $(1)/lib/gluon/setup-mode/rc.d/K90network
|
||||||
|
|
||||||
for link in $(init_links); do \
|
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
|
#!/bin/sh
|
||||||
|
|
||||||
|
|
||||||
setup_mode_enable() {
|
setup_mode_enable() {
|
||||||
local enabled="$(uci -q get 'gluon-setup-mode.@setup_mode[0].enabled')"
|
local enabled="$(uci -q get 'gluon-setup-mode.@setup_mode[0].enabled')"
|
||||||
local configured="$(uci -q get 'gluon-setup-mode.@setup_mode[0].configured')"
|
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