diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-12 12:03:39 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-11-12 12:03:39 -0700 |
commit | 76cef6c7dd3c42f1511486800760d78357624edc (patch) | |
tree | 6048ce56841b3a0ed4afad42cfb43fe3372f220c | |
parent | a0386a75584842d01b312d8c6990857c85fb0d65 (diff) |
libdhcp: Reduce stack use
-rwxr-xr-x | build-aux/stack.c.gen | 6 | ||||
-rw-r--r-- | libdhcp/dhcp_client.c | 66 |
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); |