Add dhclient(8).
This commit is contained in:
parent
c35a856091
commit
946b10df27
1
Makefile
1
Makefile
|
@ -12,6 +12,7 @@ libmount \
|
|||
bench \
|
||||
carray \
|
||||
checksum \
|
||||
dhclient \
|
||||
disked \
|
||||
dnsconfig \
|
||||
editor \
|
||||
|
|
|
@ -118,6 +118,12 @@ system_initrd=$(maybe_compressed boot/system.initrd)
|
|||
ports=$(ls repository | sed 's/\.tix\.tar\.xz//')
|
||||
|
||||
mkdir -p boot/grub
|
||||
mkdir -p boot/grub/init
|
||||
|
||||
echo "furthermore" > boot/grub/init/furthermore
|
||||
# TODO: Possibly use a 'try' feature to not warn in case it was already unset.
|
||||
echo "unset require dhclient" > boot/grub/init/network-no-dhclient
|
||||
|
||||
exec > boot/grub/grub.cfg
|
||||
|
||||
for hook in \
|
||||
|
@ -184,6 +190,7 @@ else
|
|||
fi
|
||||
set enable_src=true
|
||||
set enable_network_drivers=
|
||||
set enable_dhclient=true
|
||||
|
||||
export version
|
||||
export machine
|
||||
|
@ -194,6 +201,7 @@ export default
|
|||
export no_random_seed
|
||||
export enable_src
|
||||
export enable_network_drivers
|
||||
export enable_dhclient
|
||||
EOF
|
||||
|
||||
if [ -n "$ports" ]; then
|
||||
|
@ -283,6 +291,12 @@ cat << EOF
|
|||
multiboot /$kernel \$no_random_seed \$enable_network_drivers "\$@"
|
||||
echo done
|
||||
hook_kernel_post
|
||||
if ! \$enable_dhclient; then
|
||||
echo -n "Disabling dhclient ... "
|
||||
module /boot/grub/init/furthermore --create-to /etc/init/network
|
||||
module /boot/grub/init/network-no-dhclient --append-to /etc/init/network
|
||||
echo done
|
||||
fi
|
||||
if [ \$no_random_seed != --no-random-seed ]; then
|
||||
echo -n "Loading /boot/random.seed (256) ... "
|
||||
module /boot/random.seed --random-seed
|
||||
|
@ -430,6 +444,18 @@ else
|
|||
}
|
||||
fi
|
||||
|
||||
if \$enable_dhclient; then
|
||||
menuentry "Disable DHCP client" {
|
||||
enable_dhclient=false
|
||||
configfile /boot/grub/advanced.cfg
|
||||
}
|
||||
else
|
||||
menuentry "Enable DHCP client" {
|
||||
enable_dhclient=true
|
||||
configfile /boot/grub/advanced.cfg
|
||||
}
|
||||
fi
|
||||
|
||||
menuentry "Select binary packages..." {
|
||||
configfile /boot/grub/tix.cfg
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
dhclient
|
|
@ -0,0 +1,29 @@
|
|||
SOFTWARE_MEANT_FOR_SORTIX=1
|
||||
include ../build-aux/platform.mak
|
||||
include ../build-aux/compiler.mak
|
||||
include ../build-aux/version.mak
|
||||
include ../build-aux/dirs.mak
|
||||
|
||||
OPTLEVEL?=$(DEFAULT_OPTLEVEL)
|
||||
CFLAGS?=$(OPTLEVEL)
|
||||
|
||||
CFLAGS += -Wall -Wextra
|
||||
|
||||
BINARIES = dhclient
|
||||
#MANPAGES8 = dhclient.8
|
||||
|
||||
all: $(BINARIES)
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)$(SBINDIR)
|
||||
install $(BINARIES) $(DESTDIR)$(SBINDIR)
|
||||
#mkdir -p $(DESTDIR)$(MANDIR)/man8
|
||||
#install $(MANPAGES8) $(DESTDIR)$(MANDIR)/man8
|
||||
|
||||
%: %.c
|
||||
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(BINARIES)
|
|
@ -0,0 +1,798 @@
|
|||
/*
|
||||
* Copyright (c) 2016, 2017 Jonas 'Sortie' Termansen.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* dhclient.c
|
||||
* Dynamic Host Configuration Protocol client.
|
||||
*/
|
||||
|
||||
#if defined(__sortix__)
|
||||
#include <sys/dnsconfig.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <endian.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <timespec.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define PORT_DHCP_SERVER 67
|
||||
#define PORT_DHCP_CLIENT 68
|
||||
|
||||
struct dhcp
|
||||
{
|
||||
uint8_t op;
|
||||
uint8_t htype;
|
||||
uint8_t hlen;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint16_t secs;
|
||||
uint16_t flags;
|
||||
uint8_t ciaddr[4];
|
||||
uint8_t yiaddr[4];
|
||||
uint8_t siaddr[4];
|
||||
uint8_t giaddr[4];
|
||||
uint8_t chaddr[16];
|
||||
uint8_t sname[64];
|
||||
uint8_t file[128];
|
||||
};
|
||||
|
||||
#define DHCP_OP_BOOTREQUEST 1
|
||||
#define DHCP_OP_BOOTREPLY 2
|
||||
#define DHCP_FLAGS_BROADCAST (1 << 15)
|
||||
#define DHCP_HTYPE_ETHERNET 1
|
||||
#define DHCP_HLEN_ETHERNET 6
|
||||
#define DHCP_MAGIC_0 99
|
||||
#define DHCP_MAGIC_1 130
|
||||
#define DHCP_MAGIC_2 83
|
||||
#define DHCP_MAGIC_3 99
|
||||
|
||||
#define OPTION_PAD 0
|
||||
#define OPTION_SUBNET 1
|
||||
#define OPTION_TIME_OFFSET 2
|
||||
#define OPTION_ROUTERS 3
|
||||
#define OPTION_DNS 6
|
||||
#define OPTION_DOMAIN_NAME 12
|
||||
#define OPTION_INTERFACE_MTU 26
|
||||
#define OPTION_BROADCAST_ADDRESS 28
|
||||
#define OPTION_NTP 42
|
||||
#define OPTION_REQUESTED_IP 50
|
||||
#define OPTION_LEASE_TIME 51
|
||||
#define OPTION_OPTION_OVERLOAD 52
|
||||
#define OPTION_DHCP_MSGTYPE 53
|
||||
#define OPTION_SERVER_IDENTIFIER 54
|
||||
#define OPTION_PARAMETER_REQUEST 55
|
||||
#define OPTION_RENEWAL_TIME 58
|
||||
#define OPTION_REBINDING_TIME 59
|
||||
#define OPTION_END 255
|
||||
|
||||
#define DHCPDISCOVER 1
|
||||
#define DHCPOFFER 2
|
||||
#define DHCPREQUEST 3
|
||||
#define DHCPDECLINE 4
|
||||
#define DHCPACK 5
|
||||
#define DHCPNAK 6
|
||||
#define DHCPRELEASE 7
|
||||
#define DHCPINFORM 9
|
||||
|
||||
struct dhcp_message
|
||||
{
|
||||
struct dhcp hdr;
|
||||
unsigned char magic[4];
|
||||
unsigned char options[65536 - (sizeof(struct dhcp) + 4)];
|
||||
};
|
||||
|
||||
enum option_state
|
||||
{
|
||||
OPTION_STATE_OPTIONS,
|
||||
OPTION_STATE_FILE,
|
||||
OPTION_STATE_SNAME,
|
||||
OPTION_STATE_DONE,
|
||||
};
|
||||
|
||||
struct option_iterate
|
||||
{
|
||||
struct dhcp* hdr;
|
||||
unsigned char* options;
|
||||
size_t offset;
|
||||
size_t length;
|
||||
enum option_state state;
|
||||
bool has_sname_options;
|
||||
bool has_file_options;
|
||||
};
|
||||
|
||||
static void option_iterate_begin(struct option_iterate* iter,
|
||||
struct dhcp* hdr,
|
||||
unsigned char* options,
|
||||
size_t length)
|
||||
{
|
||||
memset(iter, 0, sizeof(*iter));
|
||||
iter->hdr = hdr;
|
||||
iter->options = options;
|
||||
iter->length = length;
|
||||
}
|
||||
|
||||
static void option_iterate_begin_msg(struct option_iterate* iter,
|
||||
struct dhcp_message* msg,
|
||||
size_t length)
|
||||
{
|
||||
size_t offset = offsetof(struct dhcp_message, options);
|
||||
assert(offset <= length);
|
||||
option_iterate_begin(iter, &msg->hdr, msg->options, length - offset);
|
||||
}
|
||||
|
||||
static bool option_iterate_array(struct option_iterate* iter,
|
||||
unsigned char* options,
|
||||
size_t length,
|
||||
unsigned char* out_option,
|
||||
unsigned char* out_optlen,
|
||||
unsigned char** out_data)
|
||||
{
|
||||
while ( iter->offset < length )
|
||||
{
|
||||
unsigned char option = options[iter->offset++];
|
||||
if ( option == OPTION_PAD )
|
||||
continue;
|
||||
if ( option == OPTION_END )
|
||||
break;
|
||||
if ( iter->offset == length )
|
||||
return false;
|
||||
unsigned char optlen = options[iter->offset++];
|
||||
if ( length - iter->offset < optlen )
|
||||
return false;
|
||||
unsigned char* data = iter->options + iter->offset;
|
||||
*out_option = option;
|
||||
*out_optlen = optlen;
|
||||
*out_data = data;
|
||||
iter->offset += optlen;
|
||||
if ( option == OPTION_OPTION_OVERLOAD )
|
||||
{
|
||||
if ( optlen != 1 )
|
||||
return false;
|
||||
if ( iter->state == OPTION_STATE_OPTIONS )
|
||||
{
|
||||
if ( data[0] & 1 << 0 )
|
||||
iter->has_sname_options = true;
|
||||
if ( data[0] & 1 << 1 )
|
||||
iter->has_file_options = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
static bool option_iterate(struct option_iterate* iter,
|
||||
unsigned char* out_option,
|
||||
unsigned char* out_optlen,
|
||||
unsigned char** out_data)
|
||||
{
|
||||
if ( iter->state == OPTION_STATE_OPTIONS )
|
||||
{
|
||||
if ( option_iterate_array(iter, iter->options, iter->length,
|
||||
out_option, out_optlen, out_data) )
|
||||
return true;
|
||||
iter->state = OPTION_STATE_SNAME;
|
||||
iter->offset = 0;
|
||||
}
|
||||
if ( iter->state == OPTION_STATE_SNAME )
|
||||
{
|
||||
if ( iter->has_sname_options &&
|
||||
option_iterate_array(iter, iter->hdr->sname,
|
||||
sizeof(iter->hdr->sname), out_option,
|
||||
out_optlen, out_data) )
|
||||
return true;
|
||||
iter->state = OPTION_STATE_FILE;
|
||||
iter->offset = 0;
|
||||
}
|
||||
if ( iter->state == OPTION_STATE_FILE )
|
||||
{
|
||||
if ( iter->has_file_options &&
|
||||
option_iterate_array(iter, iter->hdr->file,
|
||||
sizeof(iter->hdr->file), out_option,
|
||||
out_optlen, out_data) )
|
||||
return true;
|
||||
iter->state = OPTION_STATE_DONE;
|
||||
iter->offset = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool option_search(struct option_iterate* iter,
|
||||
unsigned char search_option,
|
||||
unsigned char* out_optlen,
|
||||
unsigned char** out_data)
|
||||
{
|
||||
enum option_state saved_state = iter->state;
|
||||
size_t saved_offset = iter->offset;
|
||||
iter->state = OPTION_STATE_OPTIONS;
|
||||
iter->offset = 0;
|
||||
bool result = false;
|
||||
unsigned char option;
|
||||
unsigned char optlen;
|
||||
unsigned char* data;
|
||||
while ( option_iterate(iter, &option, &optlen, &data) )
|
||||
{
|
||||
if ( option == search_option )
|
||||
{
|
||||
result = true;
|
||||
*out_optlen = optlen;
|
||||
*out_data = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iter->state = saved_state;
|
||||
iter->offset = saved_offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
static const unsigned char requests[] =
|
||||
{
|
||||
OPTION_SUBNET,
|
||||
OPTION_TIME_OFFSET,
|
||||
OPTION_ROUTERS,
|
||||
OPTION_DNS,
|
||||
OPTION_DOMAIN_NAME,
|
||||
OPTION_INTERFACE_MTU,
|
||||
OPTION_NTP,
|
||||
};
|
||||
|
||||
static size_t add_option_byte(unsigned char* options,
|
||||
size_t optsmax,
|
||||
size_t offset,
|
||||
unsigned char byte)
|
||||
{
|
||||
if ( optsmax <= offset )
|
||||
errx(1, "too many dhcp options");
|
||||
options[offset++] = byte;
|
||||
return offset;
|
||||
}
|
||||
|
||||
static size_t add_option(unsigned char* options,
|
||||
size_t optsmax,
|
||||
size_t offset,
|
||||
unsigned char option,
|
||||
unsigned char optlen,
|
||||
const unsigned char* data)
|
||||
{
|
||||
offset = add_option_byte(options, optsmax, offset, option);
|
||||
offset = add_option_byte(options, optsmax, offset, optlen);
|
||||
for ( size_t i = 0; i < optlen; i++ )
|
||||
offset = add_option_byte(options, optsmax, offset, data[i]);
|
||||
return offset;
|
||||
}
|
||||
|
||||
static bool check_dchp_message(struct dhcp_message* msg,
|
||||
size_t amount,
|
||||
unsigned char* chaddr,
|
||||
uint32_t xid)
|
||||
{
|
||||
if ( (size_t) amount < sizeof(msg->hdr) )
|
||||
return false;
|
||||
if ( (size_t) amount < sizeof(msg->hdr) + sizeof(msg->magic) )
|
||||
return false;
|
||||
if ( msg->hdr.op != DHCP_OP_BOOTREPLY )
|
||||
return false;
|
||||
if ( msg->hdr.htype != DHCP_HTYPE_ETHERNET ||
|
||||
msg->hdr.hlen != DHCP_HLEN_ETHERNET )
|
||||
return false;
|
||||
if ( memcmp(msg->hdr.chaddr, chaddr, sizeof(msg->hdr.chaddr)) != 0 )
|
||||
return false;
|
||||
if ( msg->hdr.xid != htobe32(xid) )
|
||||
return false;
|
||||
if ( msg->magic[0] != DHCP_MAGIC_0 ||
|
||||
msg->magic[1] != DHCP_MAGIC_1 ||
|
||||
msg->magic[2] != DHCP_MAGIC_2 ||
|
||||
msg->magic[3] != DHCP_MAGIC_3 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ready(void)
|
||||
{
|
||||
const char* readyfd_env = getenv("READYFD");
|
||||
if ( !readyfd_env )
|
||||
return;
|
||||
int readyfd = atoi(readyfd_env);
|
||||
char c = '\n';
|
||||
write(readyfd, &c, 1);
|
||||
close(readyfd);
|
||||
unsetenv("READYFD");
|
||||
}
|
||||
|
||||
static void compact_arguments(int* argc, char*** argv)
|
||||
{
|
||||
for ( int i = 0; i < *argc; i++ )
|
||||
{
|
||||
while ( i < *argc && !(*argv)[i] )
|
||||
{
|
||||
for ( int n = i; n < *argc; n++ )
|
||||
(*argv)[n] = (*argv)[n+1];
|
||||
(*argc)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
|
||||
const char* argv0 = argv[0];
|
||||
for ( int i = 1; i < argc; i++ )
|
||||
{
|
||||
const char* arg = argv[i];
|
||||
if ( arg[0] != '-' || !arg[1] )
|
||||
continue;
|
||||
argv[i] = NULL;
|
||||
if ( !strcmp(arg, "--") )
|
||||
break;
|
||||
if ( arg[1] != '-' )
|
||||
{
|
||||
char c;
|
||||
while ( (c = *++arg) ) switch ( c )
|
||||
{
|
||||
default:
|
||||
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s: unknown option: %s\n", argv0, arg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
compact_arguments(&argc, &argv);
|
||||
|
||||
#if defined(__sortix__)
|
||||
if ( argc <= 1 )
|
||||
{
|
||||
printf("Usage: %s <interface>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
const char* if_name = argv[1];
|
||||
if ( 3 <= argc )
|
||||
errx(1, "unexpected extra operand `%s'", argv[2]);
|
||||
|
||||
int dev_fd = open("/dev", O_RDONLY | O_DIRECTORY);
|
||||
if ( dev_fd < 0 )
|
||||
err(1, "/dev");
|
||||
int if_fd = openat(dev_fd, if_name, O_RDWR);
|
||||
if ( if_fd < 0 )
|
||||
err(1, "%s", if_name);
|
||||
close(dev_fd);
|
||||
|
||||
int type = ioctl(if_fd, IOCGETTYPE);
|
||||
if ( type < 0 )
|
||||
err(1, "%s: ioctl: IOCGETTYPE", if_name);
|
||||
if ( IOC_TYPE(type) != IOC_TYPE_NETWORK_INTERFACE )
|
||||
errx(1, "%s: Not a network interface", if_name);
|
||||
|
||||
struct if_info info;
|
||||
if ( ioctl(if_fd, NIOC_GETINFO, &info) < 0 )
|
||||
err(1, "%s: ioctl: NIOC_GETINFO", if_name);
|
||||
if ( info.type == IF_TYPE_LOOPBACK )
|
||||
{
|
||||
printf("%s: Loopback interface does not need to be configured\n",
|
||||
if_name);
|
||||
return 0;
|
||||
}
|
||||
if ( info.type != IF_TYPE_ETHERNET )
|
||||
errx(1, "%s: ioctl: NIOC_GETINFO: unknown device type", if_name);
|
||||
if ( info.addrlen != 6 )
|
||||
errx(1, "%s: ioctl: NIOC_GETINFO: bogus address length", if_name);
|
||||
// TODO: struct ether_addr
|
||||
unsigned char ethaddr[6];
|
||||
memcpy(ethaddr, info.addr, 6);
|
||||
|
||||
#else
|
||||
unsigned char ethaddr[6] = { 00, 25, 22, 04, 95, 83 };
|
||||
#endif
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if ( fd < 0 )
|
||||
err(1, "socket");
|
||||
|
||||
#if defined(__sortix__)
|
||||
if ( setsockopt(fd, SOL_SOCKET, SO_BINDTOINDEX, &info.linkid,
|
||||
sizeof(info.linkid)) < 0 )
|
||||
err(1, "setsockopt: SO_BINDTOINDEX");
|
||||
#endif
|
||||
|
||||
int enable = 1;
|
||||
if ( setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)) < 0 )
|
||||
err(1, "setsockopt: SO_BROADCAST");
|
||||
|
||||
struct sockaddr_in local;
|
||||
memset(&local, 0, sizeof(local));
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_port = htobe16(PORT_DHCP_CLIENT);
|
||||
local.sin_addr.s_addr = htobe32(INADDR_ANY);
|
||||
|
||||
if ( bind(fd, (const struct sockaddr*) &local, sizeof(local)) < 0 )
|
||||
err(1, "bind");
|
||||
|
||||
struct sockaddr_in dest;
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
dest.sin_family = AF_INET;
|
||||
dest.sin_port = htobe16(PORT_DHCP_SERVER);
|
||||
dest.sin_addr.s_addr = htobe32(INADDR_BROADCAST);
|
||||
|
||||
struct sockaddr_in remote;
|
||||
socklen_t remote_len = sizeof(remote);
|
||||
|
||||
#if defined(__sortix__)
|
||||
printf("%s: Waiting for interface to come up\n", if_name);
|
||||
// TODO: This can block indefinitely. Run ready() if this step times out.
|
||||
if ( ioctl(if_fd, NIOC_WAITLINKSTATUS, 1) < 0 )
|
||||
err(1, "%s: ioctl: NIOC_WAITLINKSTATUS", if_name);
|
||||
printf("%s: Interface is up\n", if_name);
|
||||
#endif
|
||||
|
||||
// TODO: "The client SHOULD wait a random time between one and ten seconds
|
||||
// to desynchronize the use of DHCP at startup."
|
||||
// Ten seconds seems excessive in today's world, but a small random
|
||||
// delay seems reasonable. There are randomness in retransmissions so
|
||||
// maybe this doesn't benefit so much.
|
||||
|
||||
#if defined(__sortix__)
|
||||
uint32_t xid = arc4random();
|
||||
#else
|
||||
uint32_t xid = rand();
|
||||
#endif
|
||||
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
unsigned int retransmissions = 0;
|
||||
|
||||
unsigned char chaddr[16];
|
||||
memset(chaddr, 0, sizeof(chaddr));
|
||||
memcpy(chaddr, ethaddr, 6);
|
||||
|
||||
static struct dhcp_message msg;
|
||||
unsigned char* opts = msg.options;
|
||||
size_t msgsize;
|
||||
size_t optsoff;
|
||||
size_t optsmax = sizeof(msg.options);
|
||||
unsigned char option;
|
||||
unsigned char optlen = 0;
|
||||
unsigned char* optdata = NULL;
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec begun = now;
|
||||
struct timespec last_sent;
|
||||
struct timespec timeout;
|
||||
|
||||
last_sent = timespec_make(-1, 0);
|
||||
timeout = timespec_make(0, 0);
|
||||
|
||||
unsigned char yiaddr[4];
|
||||
unsigned char server_identifier[4];
|
||||
char remote_host_str[NI_MAXHOST];
|
||||
char remote_serv_str[NI_MAXSERV];
|
||||
char yiaddr_str[INET_ADDRSTRLEN];
|
||||
while ( true )
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec since_sent = timespec_sub(now, last_sent);
|
||||
if ( timespec_ge(since_sent, timeout) )
|
||||
{
|
||||
struct timespec since_begun = timespec_sub(now, begun);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.hdr.op = DHCP_OP_BOOTREQUEST;
|
||||
msg.hdr.htype = DHCP_HTYPE_ETHERNET;
|
||||
msg.hdr.hlen = DHCP_HLEN_ETHERNET;
|
||||
msg.hdr.xid = htobe32(xid);
|
||||
msg.hdr.secs = htobe16((uint16_t) since_begun.tv_sec);
|
||||
msg.hdr.flags = htobe16(DHCP_FLAGS_BROADCAST);
|
||||
memcpy(msg.hdr.chaddr, chaddr, sizeof(chaddr));
|
||||
msg.magic[0] = DHCP_MAGIC_0;
|
||||
msg.magic[1] = DHCP_MAGIC_1;
|
||||
msg.magic[2] = DHCP_MAGIC_2;
|
||||
msg.magic[3] = DHCP_MAGIC_3;
|
||||
|
||||
optsoff = 0;
|
||||
option = DHCPDISCOVER;
|
||||
optsoff = add_option(opts, optsmax, optsoff, OPTION_DHCP_MSGTYPE,
|
||||
1, &option);
|
||||
optsoff = add_option(opts, optsmax, optsoff,
|
||||
OPTION_PARAMETER_REQUEST, sizeof(requests),
|
||||
requests);
|
||||
// TODO: Maybe send hostname.
|
||||
optsoff = add_option_byte(opts, optsmax, optsoff, OPTION_END);
|
||||
|
||||
if ( retransmissions == 0 )
|
||||
printf("%s: Broadcasting DHCPDISCOVER\n", if_name);
|
||||
else
|
||||
printf("%s: Broadcasting DHCPDISCOVER (attempt %i)\n", if_name,
|
||||
retransmissions + 1);
|
||||
|
||||
msgsize = sizeof(msg.hdr) + sizeof(msg.magic) + optsoff;
|
||||
// TODO: This can fail temporarily like with ENOBUFS.
|
||||
if ( sendto(fd, &msg, msgsize, 0, (const struct sockaddr*) &dest,
|
||||
sizeof(dest)) < 0 )
|
||||
err(1, "send");
|
||||
|
||||
last_sent = now;
|
||||
timeout = timespec_make(1 << retransmissions,
|
||||
arc4random_uniform(1000000000));
|
||||
if ( retransmissions < 6 )
|
||||
retransmissions++;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s: error: DHCPDISCOVER timed out\n", if_name);
|
||||
ready();
|
||||
// TODO: Technically restart the initialization.
|
||||
retransmissions = 0;
|
||||
}
|
||||
}
|
||||
struct timespec left =
|
||||
timespec_sub(timespec_add(last_sent, timeout), now);
|
||||
struct pollfd pfd = { 0 };
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
int num_events = ppoll(&pfd, 1, &left, NULL);
|
||||
if ( num_events < 0 )
|
||||
err(1, "ppoll");
|
||||
if ( num_events == 0 )
|
||||
continue;
|
||||
ssize_t amount = recvfrom(fd, &msg, sizeof(msg), 0,
|
||||
(struct sockaddr*) &remote, &remote_len);
|
||||
if ( amount < 0 )
|
||||
err(1, "recv");
|
||||
// TODO: Check the remote port is correct?
|
||||
if ( !check_dchp_message(&msg, amount, chaddr, xid) )
|
||||
continue;
|
||||
struct option_iterate iter;
|
||||
option_iterate_begin_msg(&iter, &msg, amount);
|
||||
if ( !option_search(&iter, OPTION_DHCP_MSGTYPE, &optlen, &optdata) ||
|
||||
optlen != 1 ||
|
||||
optdata[0] != DHCPOFFER )
|
||||
continue;
|
||||
if ( !option_search(&iter, OPTION_SERVER_IDENTIFIER, &optlen,
|
||||
&optdata) || optlen != 4 )
|
||||
continue;
|
||||
memcpy(server_identifier, optdata, 4);
|
||||
memcpy(yiaddr, msg.hdr.yiaddr, 4);
|
||||
getnameinfo((const struct sockaddr*) &remote, remote_len,
|
||||
remote_host_str, sizeof(remote_host_str),
|
||||
remote_serv_str, sizeof(remote_serv_str),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV);
|
||||
inet_ntop(AF_INET, yiaddr, yiaddr_str, sizeof(yiaddr_str));
|
||||
printf("%s: DHCPOFFER of %s from %s:%s\n",
|
||||
if_name, yiaddr_str, remote_host_str, remote_serv_str);
|
||||
break;
|
||||
}
|
||||
|
||||
last_sent = timespec_make(-1, 0);
|
||||
timeout = timespec_make(0, 0);
|
||||
retransmissions = 0;
|
||||
|
||||
unsigned char subnet[4];
|
||||
unsigned char router[4];
|
||||
#if defined(__sortix__)
|
||||
size_t dns_count = 0;
|
||||
unsigned char dns[DNSCONFIG_MAX_SERVERS][4];
|
||||
#endif
|
||||
uint32_t lease_time = 0;
|
||||
while ( true )
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec since_sent = timespec_sub(now, last_sent);
|
||||
if ( timespec_le(timeout, since_sent) )
|
||||
{
|
||||
struct timespec since_begun = timespec_sub(now, begun);
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.hdr.op = DHCP_OP_BOOTREQUEST;
|
||||
msg.hdr.htype = DHCP_HTYPE_ETHERNET;
|
||||
msg.hdr.hlen = DHCP_HLEN_ETHERNET;
|
||||
msg.hdr.xid = htobe32(xid);
|
||||
msg.hdr.secs = htobe16((uint16_t) since_begun.tv_sec);
|
||||
msg.hdr.flags = htobe16(DHCP_FLAGS_BROADCAST);
|
||||
memcpy(msg.hdr.chaddr, chaddr, sizeof(chaddr));
|
||||
msg.magic[0] = DHCP_MAGIC_0;
|
||||
msg.magic[1] = DHCP_MAGIC_1;
|
||||
msg.magic[2] = DHCP_MAGIC_2;
|
||||
msg.magic[3] = DHCP_MAGIC_3;
|
||||
|
||||
optsoff = 0;
|
||||
option = DHCPREQUEST;
|
||||
optsoff = add_option(opts, optsmax, optsoff, OPTION_DHCP_MSGTYPE,
|
||||
1, &option);
|
||||
optsoff = add_option(opts, optsmax, optsoff,
|
||||
OPTION_PARAMETER_REQUEST, sizeof(requests),
|
||||
requests);
|
||||
optsoff = add_option(opts, optsmax, optsoff,
|
||||
OPTION_SERVER_IDENTIFIER,
|
||||
sizeof(server_identifier), server_identifier);
|
||||
optsoff = add_option(opts, optsmax, optsoff, OPTION_REQUESTED_IP,
|
||||
sizeof(yiaddr), yiaddr);
|
||||
// TODO: Maybe send hostname.
|
||||
optsoff = add_option_byte(opts, optsmax, optsoff, OPTION_END);
|
||||
|
||||
if ( retransmissions == 0 )
|
||||
printf("%s: Broadcasting DHCPREQUEST\n", if_name);
|
||||
else
|
||||
printf("%s: Broadcasting DHCPREQUEST (attempt %i)\n", if_name,
|
||||
retransmissions + 1);
|
||||
|
||||
msgsize = sizeof(msg.hdr) + sizeof(msg.magic) + optsoff;
|
||||
if ( sendto(fd, &msg, msgsize, 0, (const struct sockaddr*) &dest,
|
||||
sizeof(dest)) < 0 )
|
||||
err(1, "send");
|
||||
|
||||
last_sent = now;
|
||||
timeout = timespec_make(1 << retransmissions,
|
||||
arc4random_uniform(1000000000));
|
||||
if ( retransmissions < 6 )
|
||||
retransmissions++;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s: error: DHCPDISCOVER timed out\n", if_name);
|
||||
ready();
|
||||
// TODO: Technically restart the initialization.
|
||||
retransmissions = 0;
|
||||
}
|
||||
}
|
||||
struct timespec left =
|
||||
timespec_sub(timespec_add(last_sent, timeout), now);
|
||||
struct pollfd pfd = { 0 };
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
int num_events = ppoll(&pfd, 1, &left, NULL);
|
||||
if ( num_events < 0 )
|
||||
err(1, "ppoll");
|
||||
if ( num_events == 0 )
|
||||
continue;
|
||||
struct sockaddr_in peer;
|
||||
socklen_t peer_len = sizeof(peer);
|
||||
ssize_t amount = recvfrom(fd, &msg, sizeof(msg), 0,
|
||||
(struct sockaddr*) &peer, &peer_len);
|
||||
if ( amount < 0 )
|
||||
err(1, "recv");
|
||||
if ( memcmp(&peer, &remote, remote_len) != 0 )
|
||||
continue;
|
||||
if ( !check_dchp_message(&msg, amount, chaddr, xid) )
|
||||
continue;
|
||||
struct option_iterate iter;
|
||||
option_iterate_begin_msg(&iter, &msg, amount);
|
||||
// TODO: Log proper errors for the below conditions.
|
||||
if ( !option_search(&iter, OPTION_DHCP_MSGTYPE, &optlen, &optdata) ||
|
||||
optlen != 1 ||
|
||||
optdata[0] != DHCPACK )
|
||||
continue;
|
||||
if ( !option_search(&iter, OPTION_SERVER_IDENTIFIER, &optlen,
|
||||
&optdata) || optlen != 4 )
|
||||
continue;
|
||||
memcpy(server_identifier, optdata, 4);
|
||||
if ( !option_search(&iter, OPTION_SUBNET, &optlen, &optdata) ||
|
||||
optlen != 4 )
|
||||
continue;
|
||||
memcpy(subnet, optdata, 4);
|
||||
if ( !option_search(&iter, OPTION_ROUTERS, &optlen, &optdata) ||
|
||||
optlen < 4 )
|
||||
continue;
|
||||
memcpy(router, optdata, 4);
|
||||
if ( !option_search(&iter, OPTION_LEASE_TIME, &optlen, &optdata) ||
|
||||
optlen != 4 )
|
||||
continue;
|
||||
lease_time = (uint32_t) optdata[0] << 24 |
|
||||
(uint32_t) optdata[1] << 16 |
|
||||
(uint32_t) optdata[2] << 8 |
|
||||
(uint32_t) optdata[3] << 0;
|
||||
// TODO: Verify yiaddr is what we requested (bait and switch).
|
||||
memcpy(yiaddr, msg.hdr.yiaddr, 4);
|
||||
#if defined(__sortix__)
|
||||
if ( option_search(&iter, OPTION_DNS, &optlen, &optdata) )
|
||||
{
|
||||
size_t offset = 0;
|
||||
for ( ; dns_count < DNSCONFIG_MAX_SERVERS && 4 <= optlen - offset;
|
||||
dns_count++ )
|
||||
{
|
||||
dns[dns_count][0] = optdata[offset++];
|
||||
dns[dns_count][1] = optdata[offset++];
|
||||
dns[dns_count][2] = optdata[offset++];
|
||||
dns[dns_count][3] = optdata[offset++];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("%s: DHCPACK of %s from %s:%s\n",
|
||||
if_name, yiaddr_str, remote_host_str, remote_serv_str);
|
||||
break;
|
||||
}
|
||||
|
||||
char router_str[INET_ADDRSTRLEN];
|
||||
char subnet_str[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, router, router_str, sizeof(router_str));
|
||||
inet_ntop(AF_INET, subnet, subnet_str, sizeof(subnet_str));
|
||||
printf("%s: Leased %s from %s:%s for %u seconds\n",
|
||||
if_name,
|
||||
yiaddr_str,
|
||||
remote_host_str,
|
||||
remote_serv_str,
|
||||
lease_time);
|
||||
printf("%s: Router is %s\n", if_name, router_str);
|
||||
printf("%s: Subnet is %s\n", if_name, subnet_str);
|
||||
if ( dns_count == 0 )
|
||||
printf("%s: No DNS servers were offered\n", if_name);
|
||||
else for ( size_t i = 0; i < dns_count; i++ )
|
||||
{
|
||||
char dns_str[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, dns[i], dns_str, sizeof(dns_str));
|
||||
printf("%s: DNS server %zu is %s\n", if_name, i + 1, dns_str);
|
||||
}
|
||||
|
||||
#if defined(__sortix__)
|
||||
struct if_config_inet inet_cfg;
|
||||
memcpy(&inet_cfg.address, yiaddr, sizeof(inet_cfg.address));
|
||||
memcpy(&inet_cfg.router, router, sizeof(inet_cfg.router));
|
||||
memcpy(&inet_cfg.subnet, subnet, sizeof(inet_cfg.subnet));
|
||||
if ( ioctl(if_fd, NIOC_SETCONFIG_INET, &inet_cfg) < 0 )
|
||||
err(1, "%s: ioctl: NIOC_SETCONFIG_INET", if_name);
|
||||
// TODO: This configuration should set a bit that marks the interface as
|
||||
// configured (and not in the configuration phase) and wake anything
|
||||
// waiting for the interface to come up.
|
||||
printf("%s: Configured network interface\n", if_name);
|
||||
|
||||
struct dnsconfig dnsconfig;
|
||||
memset(&dnsconfig, 0, sizeof(dnsconfig));
|
||||
dnsconfig.servers_count = dns_count;
|
||||
for ( size_t i = 0; i < dns_count; i++ )
|
||||
{
|
||||
dnsconfig.servers[i].family = AF_INET;
|
||||
dnsconfig.servers[i].addrsize = 4;
|
||||
memcpy(&dnsconfig.servers[i].addr, dns[i], 4);
|
||||
}
|
||||
if ( setdnsconfig(&dnsconfig) < 0 )
|
||||
err(1, "setdnsconfig");
|
||||
printf("%s: Configured DNS\n", if_name);
|
||||
#endif
|
||||
|
||||
ready();
|
||||
|
||||
while ( true )
|
||||
{
|
||||
sleep(lease_time);
|
||||
printf("%s: Lease for %s has expired after %u seconds\n",
|
||||
if_name, yiaddr_str, lease_time);
|
||||
// TODO: Attempt to renew lease and expire it and such.
|
||||
fprintf(stderr, "error: Lease renewal is not implemented");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
#if defined(__sortix__)
|
||||
close(if_fd);
|
||||
#endif
|
||||
}
|
|
@ -76,7 +76,8 @@ Delete a resolver:
|
|||
.Sh SEE ALSO
|
||||
.Xr getdnsconfig 2 ,
|
||||
.Xr setdnsconfig 2 ,
|
||||
.Xr inet 4
|
||||
.Xr inet 4 ,
|
||||
.Xr dhclient 8
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
originally appeared in Sortix 1.1.
|
||||
|
@ -85,3 +86,6 @@ The kernel DNS resolver list is global state.
|
|||
Changes made with
|
||||
.Nm
|
||||
may be overwritten by other programs.
|
||||
In particular
|
||||
.Xr dhclient 8
|
||||
sets the resolver list automatically unless otherwise configured.
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
per if
|
||||
#program=dhclient
|
||||
#exec $program $if
|
||||
exec dhclient
|
|
@ -0,0 +1 @@
|
|||
require dhclient
|
|
@ -332,7 +332,8 @@ temporarily fail with
|
|||
.Xr inet 4 ,
|
||||
.Xr ip 4 ,
|
||||
.Xr lo 4 ,
|
||||
.Xr kernel 7
|
||||
.Xr kernel 7 ,
|
||||
.Xr dhclient 8
|
||||
.Sh STANDARDS
|
||||
.St -p1003.1-2008
|
||||
only specifies a minimal
|
||||
|
|
|
@ -143,6 +143,13 @@ It depends on the
|
|||
and
|
||||
.Sy time
|
||||
daemons.
|
||||
.It Sy dhclient
|
||||
.\" TODO: The daemon becomes ready when an attempt has been made, rather than
|
||||
.\" when it succeeded.
|
||||
Daemon that starts
|
||||
.Xr dhclient 8
|
||||
on each network interface and becomes ready when each network interface has
|
||||
been configured.
|
||||
.It Sy local
|
||||
Virtual daemon that starts daemons pertinent to the local system.
|
||||
The system provides a default implementation that does nothing.
|
||||
|
@ -154,6 +161,9 @@ system.
|
|||
.\" TODO: The daemon becomes ready when an attempt has been made, rather than
|
||||
.\" when it succeeded.
|
||||
Virtual daemon that becomes ready when the network has been configured.
|
||||
It depends on the
|
||||
.Sy dhclient
|
||||
deamon.
|
||||
Daemons can depend on this daemon if they need the network to have been
|
||||
established before they start.
|
||||
.It Sy time
|
||||
|
@ -482,6 +492,23 @@ The
|
|||
.Sy optional
|
||||
flag should only be omitted if a local daemon is critical and the boot should
|
||||
fail if the daemon fails.
|
||||
.Ss Disable network auto-configuration (DHCP)
|
||||
The
|
||||
.Sy network
|
||||
daemon depends by default on
|
||||
.Sy dhclient ,
|
||||
which does DHCP configuration of the network.
|
||||
This dependency can be removed by creating
|
||||
.Pa /etc/init/network
|
||||
with the following contents:
|
||||
.Bd -literal
|
||||
furthermore
|
||||
unset require dhclient
|
||||
.Ed
|
||||
.Pp
|
||||
This example extends the existing configuration in
|
||||
.Pa /share/init/network
|
||||
by removing a dependency.
|
||||
.Ss Creating a new virtual daemon
|
||||
The
|
||||
.Sy exampled
|
||||
|
|
|
@ -82,7 +82,8 @@ per the instructions in
|
|||
The release modification procedure lets you customize aspects such as the
|
||||
default bootloader menu option and timeout, the default hostname, the default
|
||||
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||
the live environment, control which drivers are loaded by default, and so on.
|
||||
the live environment, control which drivers are loaded by default, control which
|
||||
live environment daemons are started by default, and so on.
|
||||
.Pp
|
||||
Warning: The live environment does not come with any random entropy and entropy
|
||||
gathering is not yet implemented.
|
||||
|
@ -143,6 +144,29 @@ Only the selected ports are loaded into the live environment and installed onto
|
|||
the new installation.
|
||||
If upgrading an existing installation, then any ports not loaded will be removed
|
||||
from the installation being upgraded.
|
||||
.Pp
|
||||
Ports can additionally be loaded as binary packages in the
|
||||
.Pa /repository
|
||||
directory by navigating to the advanced menu and then the select binary packages
|
||||
submenu and then selecting which ports.
|
||||
.Pp
|
||||
The network drivers can be disabled by navigating to the advanced menu and
|
||||
selecting
|
||||
.Sy Disable network drivers .
|
||||
It can be useful to disable the network drivers if it's undesirable to put the
|
||||
system on the network for security reasons.
|
||||
You can disable network drivers by default by editing the bootloader
|
||||
configuration as described below after completing the installation.
|
||||
.Pp
|
||||
By default
|
||||
.Xr dhclient 8
|
||||
will automatically configure
|
||||
.Xr ether 4
|
||||
network interfaces with DHCP and bring up network connectivity.
|
||||
The DHCP client can be disabled by navigating to the advanced menu and selecting
|
||||
.Sy Disable DHCP client ,
|
||||
which is useful if you want to manually configure the network or not expose the
|
||||
system until you are ready.
|
||||
.Ss Installer
|
||||
This guide assumes you selected the operating system installation option in the
|
||||
bootloader.
|
||||
|
|
|
@ -262,6 +262,8 @@ If the selected menu option itself is a submenu, it can be appended with a
|
|||
.Sy '>'
|
||||
and another selection to pick a default menu option in that submenu, and so on.
|
||||
(Default: 0)
|
||||
.It Sy enable_dhclient
|
||||
TODO: Document this.
|
||||
.It Sy enable_network_drivers
|
||||
An additional
|
||||
.Xr kernel 7
|
||||
|
|
|
@ -16,7 +16,8 @@ configuration as described in section 5 of the manual.
|
|||
The release modification procedure lets you customize aspects such as the
|
||||
default bootloader menu option and timeout, the default hostname, the default
|
||||
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||
the live environment, control which drivers are loaded by default, and so on.
|
||||
the live environment, control which drivers are loaded by default, control which
|
||||
live environment daemons are started by default, and so on.
|
||||
.Ss Prerequisites
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
|
@ -399,6 +400,16 @@ security reasons or to work around driver issues:
|
|||
tix-iso-bootconfig --disable-network-drivers bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Ss Disable DHCP Auto-Configuration By Default
|
||||
To customize a release so
|
||||
.Xr dhclient 8
|
||||
doesn't automatically configure network interfaces using DHCP, useful if one
|
||||
wants to manually configure network interfaces with
|
||||
.Xr ifconfig 8 .
|
||||
.Bd -literal
|
||||
tix-iso-bootconfig --disable-dhclient bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr xorriso 1 ,
|
||||
.Xr development 7 ,
|
||||
|
|
|
@ -29,7 +29,8 @@ per the instructions in
|
|||
The release modification procedure lets you customize aspects such as the
|
||||
default bootloader menu option and timeout, the default hostname, the default
|
||||
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||
the live environment, control which drivers are loaded by default, and so on.
|
||||
the live environment, control which drivers are loaded by default, control which
|
||||
live environment daemons are started by default, and so on.
|
||||
.Pp
|
||||
Warning: The live environment does not come with any random entropy and entropy
|
||||
gathering is not yet implemented.
|
||||
|
|
|
@ -22,6 +22,7 @@ append_title="modified by $(id -un)@$(hostname)"
|
|||
default=
|
||||
directory=
|
||||
enable_append_title=true
|
||||
enable_dhclient=
|
||||
enable_network_drivers=
|
||||
enable_src=
|
||||
liveconfig=
|
||||
|
@ -51,9 +52,11 @@ for argument do
|
|||
--default=*) default=$parameter ;;
|
||||
--default) previous_option=default ;;
|
||||
--disable-append-title) enable_append_title=false ;;
|
||||
--disable-dhclient) enable_dhclient=false ;;
|
||||
--disable-network-drivers) enable_network_drivers=false ;;
|
||||
--disable-src) enable_src=false ;;
|
||||
--enable-append-title) enable_append_title=true ;;
|
||||
--enable-dhclient) enable_dhclient=true ;;
|
||||
--enable-network-drivers) enable_network_drivers=true ;;
|
||||
--enable-src) enable_src=true ;;
|
||||
--liveconfig=*) liveconfig=$parameter ;;
|
||||
|
@ -135,6 +138,7 @@ mkdir -p -- "$directory/boot/grub"
|
|||
if [ -n "$timeout" ]; then
|
||||
printf 'timeout="%s"\n' "$timeout"
|
||||
fi
|
||||
print_enable_default_bool "$enable_dhclient" dhclient dhclient
|
||||
print_enable_default "$enable_network_drivers" network_drivers network-drivers
|
||||
print_enable_default_bool "$enable_src" src src
|
||||
if $enable_append_title; then
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
.Op Fl \-append-title Ns = Ns Ar text
|
||||
.Op Fl \-default Ns = Ns Ar default-boot-menu-option
|
||||
.Op Fl \-disable-append-title
|
||||
.Op Fl \-disable-dhclient
|
||||
.Op Fl \-disable-network-drivers
|
||||
.Op Fl \-disable-src
|
||||
.Op Fl \-enable-append-title
|
||||
.Op Fl \-enable-dhclient
|
||||
.Op Fl \-enable-network-drivers
|
||||
.Op Fl \-enable-src
|
||||
.Op Fl \-liveconfig Ns = Ns Ar liveconfig-directory
|
||||
|
@ -90,6 +92,14 @@ GRUB variable.
|
|||
Don't append anything to the bootloader menu title by appending to the
|
||||
.Sy base_menu_title
|
||||
GRUB variable.
|
||||
.It Fl \-disable-dhclient
|
||||
Disable automatic DHCP configuration by setting the
|
||||
.Sy enable_dhclient
|
||||
GRUB variable to
|
||||
.Sy false ,
|
||||
causing the bootloader to load additional configuration that turns off the
|
||||
.Xr dhclient 8
|
||||
daemon on boot.
|
||||
.It Fl \-disable-network-drivers
|
||||
Disable network drivers by setting the
|
||||
.Sy enable_network_drivers
|
||||
|
@ -113,6 +123,14 @@ to the bootloader menu title by appending to the
|
|||
GRUB variable.
|
||||
This option is on by default and can be disabled with
|
||||
.Fl \-disable-append-title .
|
||||
.It Fl \-enable-dhclient
|
||||
Enable automatic DHCP configuration by setting the
|
||||
.Sy enable_dhclient
|
||||
GRUB variable to
|
||||
.Sy true ,
|
||||
selecting the default behavior of starting the
|
||||
.Xr dhclient 8
|
||||
daemon.
|
||||
.It Fl \-enable-network-drivers
|
||||
Enable network drivers by setting the
|
||||
.Sy enable_network_drivers
|
||||
|
@ -254,10 +272,21 @@ security reasons or to work around driver issues:
|
|||
tix-iso-bootconfig --disable-network-drivers bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Ss Disable DHCP Auto-Configuration By Default
|
||||
To customize a release so
|
||||
.Xr dhclient 8
|
||||
doesn't automatically configure network interfaces using DHCP, useful if one
|
||||
wants to manually configure network interfaces with
|
||||
.Xr ifconfig 8 .
|
||||
.Bd -literal
|
||||
tix-iso-bootconfig --disable-dhclient bootconfig
|
||||
tix-iso-add sortix.iso bootconfig
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr xorriso 1 ,
|
||||
.Xr kernel 7 ,
|
||||
.Xr release-iso-bootconfig 7 ,
|
||||
.Xr release-iso-modification 7 ,
|
||||
.Xr init 8 ,
|
||||
.Xr tix-iso-add 8 ,
|
||||
.Xr tix-iso-liveconfig 8
|
||||
|
|
Loading…
Reference in New Issue