summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-12 12:03:39 -0700
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-11-12 12:03:39 -0700
commit76cef6c7dd3c42f1511486800760d78357624edc (patch)
tree6048ce56841b3a0ed4afad42cfb43fe3372f220c
parenta0386a75584842d01b312d8c6990857c85fb0d65 (diff)
libdhcp: Reduce stack use
-rwxr-xr-xbuild-aux/stack.c.gen6
-rw-r--r--libdhcp/dhcp_client.c66
2 files changed, 39 insertions, 33 deletions
diff --git a/build-aux/stack.c.gen b/build-aux/stack.c.gen
index ae05a78..97775a6 100755
--- a/build-aux/stack.c.gen
+++ b/build-aux/stack.c.gen
@@ -209,7 +209,10 @@ def main(ci_fnames: list[str]) -> None:
print("/*")
+ dbg = False
+
def nstatic(funcname: str, chain: list[str] = []) -> int:
+ nonlocal dbg
if funcname not in graph:
if f"__wrap_{funcname}" in graph:
# Handle `ld --wrap` functions
@@ -224,6 +227,8 @@ def main(ci_fnames: list[str]) -> None:
cycles.add(f"{chain[chain.index(funcname):] + [funcname]}")
return 9999999
node = graph[funcname]
+ if dbg:
+ print(f"//dbg: {funcname}\t{node.nstatic}")
return node.nstatic + max(
[0, *[nstatic(call, chain + [funcname]) for call in node.calls]]
)
@@ -234,6 +239,7 @@ def main(ci_fnames: list[str]) -> None:
for funcname in graph:
if funcname.endswith("_cr"):
+ # dbg = "dhcp" in funcname
print(f"{funcname.ljust(namelen)} {str(nstatic(funcname)).rjust(numlen)}")
print(("=" * namelen) + " " + "=" * numlen)
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index dad039c..3673d2c 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -188,23 +188,23 @@ static inline enum requirement dhcp_table5(typeof((struct dhcp_client){}.state)
/* Encode "Table 5: Fields and options used by DHCP clients"
* from
* https://datatracker.ietf.org/doc/html/rfc2131#page-38. */
-#define INC_ADDR ({ \
- enum requirement req; \
- switch (state) { \
- case STATE_SELECTING: case STATE_INIT_REBOOT: req = MUST; break; \
- case STATE_BOUND: case STATE_RENEWING: req = MUST_NOT; break; \
+#define INC_ADDR ({ \
+ enum requirement req; \
+ switch (state) { \
+ case STATE_SELECTING: case STATE_INIT_REBOOT: req = MUST; break; \
+ case STATE_BOUND: case STATE_RENEWING: req = MUST_NOT; break; \
case IMPOSSIBLE_REQUEST_STATES: default: req = _SHOULD_NOT_HAPPEN; \
- } \
- req; \
+ } \
+ req; \
})
-#define INC_SERVER ({ \
- enum requirement req; \
- switch (state) { \
- case STATE_SELECTING: req = MUST; break; \
- case STATE_INIT_REBOOT: case STATE_BOUND: case STATE_RENEWING: req = MUST_NOT; break; \
+#define INC_SERVER ({ \
+ enum requirement req; \
+ switch (state) { \
+ case STATE_SELECTING: req = MUST; break; \
+ case STATE_INIT_REBOOT: case STATE_BOUND: case STATE_RENEWING: req = MUST_NOT; break; \
case IMPOSSIBLE_REQUEST_STATES: default: req = _SHOULD_NOT_HAPPEN; \
- } \
- req; \
+ } \
+ req; \
})
struct { enum requirement cols[5]; } row;
#define ROW(...) row = (typeof(row)){{ __VA_ARGS__ }}
@@ -466,12 +466,12 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c
struct dhcp_recv_msg {
struct dhcp_msg raw;
struct {
+ uint16_t off;
uint16_t len;
- uint8_t *dat;
- } options[0x100];
- uint8_t _option_data[sizeof((struct dhcp_msg){}.options)+
- sizeof((struct dhcp_msg){}.file)+
- sizeof((struct dhcp_msg){}.sname)];
+ } options[0xff];
+ uint8_t option_dat[sizeof((struct dhcp_msg){}.options)+
+ sizeof((struct dhcp_msg){}.file)+
+ sizeof((struct dhcp_msg){}.sname)];
};
/** @return whether there is an error */
@@ -513,7 +513,7 @@ static inline void _dhcp_client_recv_consolidate_opts(struct dhcp_recv_msg *ret,
break;
default:
opt_len = dat[pos++];
- memcpy(&ret->options[opt_typ].dat[ret->options[opt_typ].len], &dat[pos], opt_len);
+ memcpy(&ret->option_dat[ret->options[opt_typ].off+ret->options[opt_typ].len], &dat[pos], opt_len);
ret->options[opt_typ].len += opt_len;
}
}
@@ -643,7 +643,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
continue;
if (!dhcp_opt_length_is_valid(opt, ret->options[opt].len))
goto ignore;
- ret->options[opt].dat = &ret->_option_data[allocated];
+ ret->options[opt].off = allocated;
allocated += ret->options[opt].len;
ret->options[opt].len = 0;
}
@@ -660,7 +660,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
goto ignore;
for (uint8_t opt = 1; opt < 255; opt++) {
enum requirement req = dhcp_table3(client->last_sent_msgtyp,
- ret->options[DHCP_OPT_DHCP_MSG_TYPE].dat[0],
+ ret->option_dat[ret->options[DHCP_OPT_DHCP_MSG_TYPE].off],
opt);
switch (req) {
case MUST:
@@ -684,7 +684,7 @@ static ssize_t dhcp_client_recv(struct dhcp_client *client, struct dhcp_recv_msg
if (ret->options[DHCP_OPT_CLASS_ID].len) {
/* https://datatracker.ietf.org/doc/html/rfc6842#page-4 */
if (ret->options[DHCP_OPT_CLASS_ID].len != client->self_id_len ||
- memcmp(ret->options[DHCP_OPT_CLASS_ID].dat, client->self_id_dat, client->self_id_len))
+ memcmp(&ret->option_dat[ret->options[DHCP_OPT_CLASS_ID].off], client->self_id_dat, client->self_id_len))
/* ignore messages that aren't to us */
goto ignore;
}
@@ -704,23 +704,23 @@ static void dhcp_client_take_lease(struct dhcp_client *client, struct dhcp_recv_
client->lease_client_addr = msg->raw.yiaddr;
client->lease_auxdata.subnet_mask = msg->options[DHCP_OPT_SUBNET_MASK].len
- ? *((struct net_ip4_addr *)msg->options[DHCP_OPT_SUBNET_MASK].dat)
+ ? *((struct net_ip4_addr *)&msg->option_dat[msg->options[DHCP_OPT_SUBNET_MASK].off])
: net_ip4_addr_zero;
client->lease_auxdata.gateway_addr = msg->options[DHCP_OPT_ROUTER].len
- ? *((struct net_ip4_addr *)msg->options[DHCP_OPT_SUBNET_MASK].dat)
+ ? *((struct net_ip4_addr *)&msg->option_dat[msg->options[DHCP_OPT_SUBNET_MASK].off])
: net_ip4_addr_zero;
client->lease_server_id =
- *((struct net_ip4_addr *)msg->options[DHCP_OPT_DHCP_SERVER_ID].dat);
+ *((struct net_ip4_addr *)&msg->option_dat[msg->options[DHCP_OPT_DHCP_SERVER_ID].off]);
uint64_t dur_ns_end =
- ((uint64_t)uint32be_decode(msg->options[DHCP_OPT_ADDRESS_TIME].dat))*NS_PER_S;
+ ((uint64_t)uint32be_decode(&msg->option_dat[msg->options[DHCP_OPT_ADDRESS_TIME].off]))*NS_PER_S;
uint64_t dur_ns_t1 = msg->options[DHCP_OPT_RENEWAL_TIME].len
- ? ((uint64_t)uint32be_decode(msg->options[DHCP_OPT_RENEWAL_TIME].dat))*NS_PER_S
+ ? ((uint64_t)uint32be_decode(&msg->option_dat[msg->options[DHCP_OPT_RENEWAL_TIME].off]))*NS_PER_S
: (dur_ns_end == DHCP_INFINITY * NS_PER_S)
? DHCP_INFINITY * NS_PER_S
: dur_ns_end/2;
uint64_t dur_ns_t2 = msg->options[DHCP_OPT_REBINDING_TIME].len
- ? ((uint64_t)uint32be_decode(msg->options[DHCP_OPT_RENEWAL_TIME].dat))*NS_PER_S
+ ? ((uint64_t)uint32be_decode(&msg->option_dat[msg->options[DHCP_OPT_RENEWAL_TIME].off]))*NS_PER_S
: (dur_ns_end == DHCP_INFINITY * NS_PER_S)
? DHCP_INFINITY * NS_PER_S
: (dur_ns_end*7)/8; /* 0.875 = 7/8 */
@@ -762,7 +762,7 @@ static __attribute__((noreturn)) void dhcp_client_run(struct dhcp_client *client
VCALL(client->sock, set_read_deadline, client->time_ns_init+CONFIG_DHCP_SELECTING_NS);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
- switch (scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].dat[0]) {
+ switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_OFFER:
/* Accept the first offer. */
dhcp_client_take_lease(client, scratch_msg, false);
@@ -784,7 +784,7 @@ static __attribute__((noreturn)) void dhcp_client_run(struct dhcp_client *client
VCALL(client->sock, set_read_deadline, 0);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
- switch (scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].dat[0]) {
+ switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
break;
@@ -826,7 +826,7 @@ static __attribute__((noreturn)) void dhcp_client_run(struct dhcp_client *client
VCALL(client->sock, set_read_deadline, client->lease_time_ns_t2);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
- switch (scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].dat[0]) {
+ switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
VCALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_INIT, 0, NULL, scratch_msg);
@@ -852,7 +852,7 @@ static __attribute__((noreturn)) void dhcp_client_run(struct dhcp_client *client
VCALL(client->sock, set_read_deadline, client->lease_time_ns_end);
switch ((r = dhcp_client_recv(client, scratch_msg))) {
case 0:
- switch (scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].dat[0]) {
+ switch (scratch_msg->option_dat[scratch_msg->options[DHCP_OPT_DHCP_MSG_TYPE].off]) {
case DHCP_MSGTYP_NAK:
VCALL(client->iface, ifdown);
dhcp_client_setstate(client, STATE_BOUND, 0, NULL, scratch_msg);