2022-02-07 06:35:29 +05:30
|
|
|
// Copyright 2004-2018 Nicholas J. Kain <njkain at gmail dot com>
|
|
|
|
// SPDX-License-Identifier: MIT
|
2013-05-08 15:57:22 +05:30
|
|
|
#include <stddef.h>
|
2014-03-20 13:37:12 +05:30
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
2013-05-08 15:57:22 +05:30
|
|
|
#include <string.h>
|
2014-03-09 23:21:49 +05:30
|
|
|
#include <arpa/inet.h>
|
2014-03-31 02:32:48 +05:30
|
|
|
#include "nk/log.h"
|
2022-08-09 23:47:31 +05:30
|
|
|
#include "nk/nstrcpy.h"
|
2014-03-11 04:59:19 +05:30
|
|
|
#include "ifchd-parse.h"
|
2014-03-10 10:22:56 +05:30
|
|
|
#include "ifchd.h"
|
|
|
|
#include "ifset.h"
|
2014-03-20 13:37:12 +05:30
|
|
|
#include "ndhc.h"
|
2014-03-10 10:22:56 +05:30
|
|
|
|
2014-03-09 22:03:20 +05:30
|
|
|
%%{
|
|
|
|
machine ipv4set_parser;
|
|
|
|
|
|
|
|
action XSt { arg_start = p; }
|
|
|
|
action IpEn {
|
2018-02-09 13:09:46 +05:30
|
|
|
ptrdiff_t arg_len = p - arg_start;
|
|
|
|
if (arg_len > 0 && (size_t)arg_len < sizeof ip4_addr) {
|
2014-03-09 22:03:20 +05:30
|
|
|
have_ip = true;
|
2018-02-09 13:09:46 +05:30
|
|
|
memcpy(ip4_addr, arg_start, (size_t)arg_len);
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
ip4_addr[arg_len] = 0;
|
|
|
|
}
|
|
|
|
action SnEn {
|
2018-02-09 13:09:46 +05:30
|
|
|
ptrdiff_t arg_len = p - arg_start;
|
|
|
|
if (arg_len > 0 && (size_t)arg_len < sizeof ip4_subnet) {
|
2014-03-09 22:03:20 +05:30
|
|
|
have_subnet = true;
|
2018-02-09 13:09:46 +05:30
|
|
|
memcpy(ip4_subnet, arg_start, (size_t)arg_len);
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
ip4_subnet[arg_len] = 0;
|
|
|
|
}
|
|
|
|
action BcEn {
|
2018-02-09 13:09:46 +05:30
|
|
|
ptrdiff_t arg_len = p - arg_start;
|
|
|
|
if (arg_len > 0 && (size_t)arg_len < sizeof ip4_bcast) {
|
2014-03-09 22:03:20 +05:30
|
|
|
have_ip = true;
|
2018-02-09 13:09:46 +05:30
|
|
|
memcpy(ip4_bcast, arg_start, (size_t)arg_len);
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
ip4_bcast[arg_len] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
v4addr = digit{1,3} '.' digit{1,3} '.' digit{1,3} '.' digit{1,3};
|
|
|
|
ip4_nobc = (v4addr > XSt % IpEn) ',' (v4addr > XSt % SnEn);
|
|
|
|
ip4_bc = (v4addr > XSt % IpEn) ',' (v4addr > XSt % SnEn) ','
|
|
|
|
(v4addr > XSt % BcEn);
|
|
|
|
main := (ip4_bc|ip4_nobc);
|
|
|
|
}%%
|
|
|
|
|
|
|
|
%% write data;
|
|
|
|
|
2022-01-12 09:05:19 +05:30
|
|
|
static int perform_ip4set(const char *buf, size_t len)
|
2014-03-09 22:03:20 +05:30
|
|
|
{
|
2014-03-09 23:21:49 +05:30
|
|
|
char ip4_addr[INET_ADDRSTRLEN];
|
|
|
|
char ip4_subnet[INET_ADDRSTRLEN];
|
|
|
|
char ip4_bcast[INET_ADDRSTRLEN];
|
2014-03-09 22:03:20 +05:30
|
|
|
const char *p = buf;
|
|
|
|
const char *pe = p + len;
|
|
|
|
const char *eof = pe;
|
2020-10-20 16:14:31 +05:30
|
|
|
const char *arg_start = p;
|
2014-03-11 04:30:08 +05:30
|
|
|
int cs = 0;
|
2014-03-09 22:03:20 +05:30
|
|
|
bool have_ip = false;
|
|
|
|
bool have_subnet = false;
|
|
|
|
bool have_bcast = false;
|
|
|
|
|
|
|
|
%% write init;
|
|
|
|
%% write exec;
|
|
|
|
|
|
|
|
if (cs < ipv4set_parser_first_final) {
|
|
|
|
log_line("%s: received invalid arguments", __func__);
|
2015-02-15 12:59:37 +05:30
|
|
|
return -1;
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// These should never trigger because of the above check, but be safe...
|
|
|
|
if (!have_ip) {
|
|
|
|
log_line("%s: No IPv4 address specified.", __func__);
|
2015-02-15 12:59:37 +05:30
|
|
|
return -1;
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
if (!have_subnet) {
|
|
|
|
log_line("%s: No IPv4 subnet specified.", __func__);
|
2015-02-15 12:59:37 +05:30
|
|
|
return -1;
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
|
2015-02-15 12:59:37 +05:30
|
|
|
return perform_ip_subnet_bcast(ip4_addr, ip4_subnet,
|
2018-10-26 16:47:39 +05:30
|
|
|
have_bcast ? ip4_bcast : (char *)0);
|
2014-03-09 22:03:20 +05:30
|
|
|
}
|
|
|
|
|
2013-05-08 15:57:22 +05:30
|
|
|
%%{
|
|
|
|
machine ifchd_parser;
|
|
|
|
|
2014-03-10 10:22:56 +05:30
|
|
|
action Reset { cl.state = STATE_NOTHING; }
|
2013-05-08 15:57:22 +05:30
|
|
|
action ArgSt { arg_start = p; }
|
|
|
|
action ArgEn {
|
2018-02-09 13:09:46 +05:30
|
|
|
ptrdiff_t al = p - arg_start;
|
|
|
|
if (al < 0 || (size_t)al > sizeof tb - 1) {
|
2013-05-08 15:57:22 +05:30
|
|
|
log_line("command argument would overflow");
|
2015-02-15 12:59:37 +05:30
|
|
|
return -99;
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
2018-02-09 13:09:46 +05:30
|
|
|
arg_len = (size_t)al;
|
2013-05-08 15:57:22 +05:30
|
|
|
memcpy(tb, arg_start, arg_len);
|
|
|
|
tb[arg_len] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
action Dispatch {
|
2015-07-03 10:19:13 +05:30
|
|
|
int pr = 0;
|
2021-04-25 14:04:37 +05:30
|
|
|
cmd_start = p + 1;
|
2014-03-10 10:22:56 +05:30
|
|
|
switch (cl.state) {
|
2015-07-03 10:19:13 +05:30
|
|
|
case STATE_IP4SET: pr = perform_ip4set(tb, arg_len); break;
|
|
|
|
case STATE_TIMEZONE: pr = perform_timezone( tb, arg_len); break;
|
|
|
|
case STATE_ROUTER: pr = perform_router(tb, arg_len); break;
|
|
|
|
case STATE_DNS: pr = perform_dns(tb, arg_len); break;
|
|
|
|
case STATE_LPRSVR: pr = perform_lprsvr(tb, arg_len); break;
|
|
|
|
case STATE_HOSTNAME: pr = perform_hostname(tb, arg_len); break;
|
|
|
|
case STATE_DOMAIN: pr = perform_domain(tb, arg_len); break;
|
|
|
|
case STATE_IPTTL: pr = perform_ipttl(tb, arg_len); break;
|
|
|
|
case STATE_MTU: pr = perform_mtu(tb, arg_len); break;
|
|
|
|
case STATE_NTPSVR: pr = perform_ntpsrv(tb, arg_len); break;
|
|
|
|
case STATE_WINS: pr = perform_wins(tb, arg_len); break;
|
|
|
|
case STATE_CARRIER: pr = perform_carrier(); break;
|
2013-05-08 15:57:22 +05:30
|
|
|
default:
|
2018-02-09 13:09:46 +05:30
|
|
|
arg_len = 0;
|
2013-05-08 15:57:22 +05:30
|
|
|
log_line("error: invalid state in dispatch_work");
|
2015-02-15 12:59:37 +05:30
|
|
|
return -99;
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
2018-02-09 13:09:46 +05:30
|
|
|
arg_len = 0;
|
2015-07-03 10:19:13 +05:30
|
|
|
if (pr == -99)
|
|
|
|
return -99;
|
|
|
|
cmdf |= pr;
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
|
|
|
|
2013-05-11 20:29:04 +05:30
|
|
|
terminator = ';' > Dispatch;
|
|
|
|
v4addr = digit{1,3} '.' digit{1,3} '.' digit{1,3} '.' digit{1,3};
|
|
|
|
ip_arg = (v4addr > ArgSt % ArgEn) terminator;
|
2014-03-09 22:03:20 +05:30
|
|
|
ip4set_arg = (((v4addr ','){1,2} v4addr) > ArgSt % ArgEn) terminator;
|
2013-05-11 20:29:04 +05:30
|
|
|
iplist_arg = (((v4addr ',')* v4addr) > ArgSt % ArgEn) terminator;
|
|
|
|
str_arg = ([^;\0]+ > ArgSt % ArgEn) terminator;
|
|
|
|
s32_arg = (extend{4} > ArgSt % ArgEn) terminator;
|
|
|
|
u16_arg = (extend{2} > ArgSt % ArgEn) terminator;
|
|
|
|
u8_arg = (extend{1} > ArgSt % ArgEn) terminator;
|
2013-05-08 15:57:22 +05:30
|
|
|
|
2014-03-10 10:43:38 +05:30
|
|
|
cmd_ip = ('routr:' % { cl.state = STATE_ROUTER; }) ip_arg;
|
2014-03-10 10:22:56 +05:30
|
|
|
cmd_ip4set = ('ip4:' % { cl.state = STATE_IP4SET; }) ip4set_arg;
|
|
|
|
cmd_iplist = ('dns:' % { cl.state = STATE_DNS; }
|
|
|
|
|'lpr:' % { cl.state = STATE_LPRSVR; }
|
|
|
|
|'ntp:' % { cl.state = STATE_NTPSVR; }
|
|
|
|
|'wins:' % { cl.state = STATE_WINS; }
|
2013-05-11 20:29:04 +05:30
|
|
|
) iplist_arg;
|
2014-03-10 10:22:56 +05:30
|
|
|
cmd_str = ('host:' % { cl.state = STATE_HOSTNAME; }
|
|
|
|
|'dom:' % { cl.state = STATE_DOMAIN; }
|
2013-05-11 20:29:04 +05:30
|
|
|
) str_arg;
|
2014-03-10 10:22:56 +05:30
|
|
|
cmd_s32 = ('tzone:' % { cl.state = STATE_TIMEZONE; }) s32_arg;
|
|
|
|
cmd_u16 = ('mtu:' % { cl.state = STATE_MTU; }) u16_arg;
|
|
|
|
cmd_u8 = ('ipttl:' % { cl.state = STATE_IPTTL; }) u8_arg;
|
2015-02-15 13:20:29 +05:30
|
|
|
cmd_none = ('carrier:' % { cl.state = STATE_CARRIER; }) terminator;
|
2013-05-08 15:57:22 +05:30
|
|
|
|
2015-02-15 13:20:29 +05:30
|
|
|
command = (cmd_ip|cmd_ip4set|cmd_iplist|cmd_str|cmd_s32|cmd_u16|cmd_u8|cmd_none);
|
2013-05-08 15:57:22 +05:30
|
|
|
main := (command > Reset)+;
|
|
|
|
}%%
|
|
|
|
|
|
|
|
%% write data;
|
|
|
|
|
|
|
|
/*
|
2015-02-15 12:59:37 +05:30
|
|
|
* Returns -99 on fatal error; that leads to peer connection being closed.
|
|
|
|
* Returns -1 if one of the commands failed.
|
|
|
|
* Returns 0 on success.
|
2013-05-08 15:57:22 +05:30
|
|
|
*/
|
2022-01-12 09:05:19 +05:30
|
|
|
int execute_buffer(const char *newbuf)
|
2013-05-08 15:57:22 +05:30
|
|
|
{
|
|
|
|
char buf[MAX_BUF * 2];
|
|
|
|
char tb[MAX_BUF];
|
2015-02-15 12:59:37 +05:30
|
|
|
int cmdf = 0;
|
2013-05-08 15:57:22 +05:30
|
|
|
|
2022-08-09 23:47:31 +05:30
|
|
|
char *snp = nstrcpy(buf, sizeof buf, cl.ibuf);
|
2021-04-25 14:04:37 +05:30
|
|
|
memset(cl.ibuf, 0, sizeof cl.ibuf);
|
2022-08-09 23:47:31 +05:30
|
|
|
if (!snp) {
|
|
|
|
log_line("%s: (%s) nstrcpy failed", client_config.interface, __func__);
|
|
|
|
return -99;
|
|
|
|
}
|
|
|
|
if (!nstrcat(buf, sizeof buf, newbuf)) {
|
|
|
|
log_line("%s: (%s) nstrcat failed", client_config.interface, __func__);
|
2015-02-15 12:59:37 +05:30
|
|
|
return -99;
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
const char *p = buf;
|
2021-04-25 06:20:08 +05:30
|
|
|
const char *pe = p + strlen(buf);
|
2020-10-20 16:14:31 +05:30
|
|
|
const char *arg_start = p;
|
2021-04-25 14:04:37 +05:30
|
|
|
const char *cmd_start = p;
|
2018-02-09 13:09:46 +05:30
|
|
|
size_t arg_len = 0;
|
2014-03-11 04:30:08 +05:30
|
|
|
int cs = 0;
|
2013-05-08 15:57:22 +05:30
|
|
|
|
|
|
|
%% write init;
|
|
|
|
%% write exec;
|
|
|
|
|
2021-04-25 14:04:37 +05:30
|
|
|
if (cs == ifchd_parser_error) {
|
|
|
|
log_line("%s: (%s) ifch received invalid commands",
|
|
|
|
client_config.interface, __func__);
|
|
|
|
return -99;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd_start != pe) {
|
2022-08-09 23:47:31 +05:30
|
|
|
if (!nstrcpy(cl.ibuf, sizeof cl.ibuf, cmd_start)) {
|
|
|
|
log_line("%s: (%s) nstrcpy failed", client_config.interface, __func__);
|
2015-02-15 12:59:37 +05:30
|
|
|
return -99;
|
2014-03-20 13:37:12 +05:30
|
|
|
}
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
|
|
|
|
2015-02-15 12:59:37 +05:30
|
|
|
return !cmdf ? 0 : -1;
|
2013-05-08 15:57:22 +05:30
|
|
|
}
|
|
|
|
|