ndhc/ndhc.h
Nicholas J. Kain a9874d4959 Support running an executable file when a new lease is acquired.
If no 'script-file = SCRIPTFILE' is specified in the configuration
file and if no '-X SCRIPTFILE' or '--script-file SCRIPTFILE'
command argument is provided, then this functionality is entirely
inactive and no associated subprocess is spawned.

Otherwise, ndhc will spawn a subprocess that runs as root that has the
sole job of forking off a subprocess that exec's the specified script in
a sanitized and fixed-state environment whenever a new DHCPv4 lease is
acquired.

Note that this script is provided no information about ndhc or the
DHCP state in the environment or in any argument fields; it is the
responsibility of this script to gather whatever information it needs
from either the filesystem or syscalls.  This design is intended to
avoid the historical problems that are associated with dhcp clients
invoking scripts.

The path of the scriptfile cannot be changed after ndhc is initially
run; ndhc forks off the privsep script subprocess that executes scripts
after it has read the configuration file and command arguments, but
before it begins processing network data; thus, it is impossible for the
network-handling process to modify or influence the script assuming
proper OS memory protection.

The privsep channel communicates that the script should be run by simply
writing a newline; anything else will result in ndhc terminating itself.

Before the recommended way to update system state after a change in
lease information was to run the fcactus program and watch the
associated leasefile for the interface for modification; now no external
program is needed for this job.
2022-02-24 03:58:37 -05:00

91 lines
2.7 KiB
C

// Copyright 2014-2020 Nicholas J. Kain <njkain at gmail dot com>
// SPDX-License-Identifier: MIT
#ifndef NJK_NDHC_NDHC_H_
#define NJK_NDHC_NDHC_H_
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include <net/if.h>
#include "nk/random.h"
enum arp_state {
ARP_QUERY = 0,
ARP_FOUND,
ARP_FAILED,
};
enum fprint_state {
FPRINT_NONE = 0,
FPRINT_INPROGRESS,
FPRINT_DONE,
};
struct client_state_t {
struct nk_random_state rnd_state;
long long leaseStartTime, renewTime, rebindTime;
long long dhcp_wake_ts;
int ifDeconfig; // Set if the interface has already been deconfigured.
int listenFd, arpFd, nlFd, rfkillFd;
int server_arp_sent, router_arp_sent;
uint32_t nlPortId;
unsigned int num_dhcp_requests, num_dhcp_renews;
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
uint32_t lease, xid;
uint8_t routerArp[6], serverArp[6];
enum arp_state server_arp_state, router_arp_state;
enum fprint_state fp_state;
bool using_dhcp_bpf, arp_is_defense, check_fingerprint, program_init,
sent_renew_or_rebind, carrier_up;
bool sent_gw_query, sent_first_announce, sent_second_announce;
};
struct client_config_t {
char interface[IFNAMSIZ]; // The name of the interface to use
char clientid[64]; // Optional client id to use
char hostname[64]; // Optional hostname to use
char vendor[64]; // Vendor identification that will be sent
uint8_t arp[6]; // Our arp address
uint32_t rfkillIdx; // Index of the corresponding rfkill device
int metric; // Metric for the default route
int ifindex; // Index number of the interface to use
int s6_notify_fd; // File descriptor for s6 notify mechanism
uint8_t clientid_len; // Length of the clientid
bool abort_if_no_lease; // Abort if no lease
bool enable_rfkill; // Listen for rfkill events
bool enable_s6_notify; // Perform s6 startup notification
};
enum {
SIGNAL_NONE = 0,
SIGNAL_EXIT,
SIGNAL_RENEW,
SIGNAL_RELEASE
};
extern struct client_config_t client_config;
extern int ifchSock[2];
extern int ifchStream[2];
extern int sockdSock[2];
extern int sockdStream[2];
extern int scriptdSock[2];
extern int scriptdStream[2];
extern char state_dir[PATH_MAX];
extern char chroot_dir[PATH_MAX];
extern char resolv_conf_d[PATH_MAX];
extern char script_file[PATH_MAX];
extern uid_t ndhc_uid;
extern gid_t ndhc_gid;
int signals_flagged(void);
bool carrier_isup(void);
void set_client_addr(const char *v);
void show_usage(void);
void signal_exit(int status);
int get_clientid_string(const char *str, size_t slen);
void print_version(void);
#endif