Hooks
lwIP » Options (lwipopts.h) » Infrastructure

## Macros

#define | LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h"
#define | LWIP_HOOK_TCP_ISN(local_ip, local_port, remote_ip, remote_port)
#define | LWIP_HOOK_TCP_INPACKET_PCB(pcb, hdr, optlen, opt1len, opt2, p)
#define | LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH(pcb, internal_len)
#define | LWIP_HOOK_TCP_OUT_ADD_TCPOPTS(p, hdr, pcb, opts)
#define | LWIP_HOOK_IP4_INPUT(pbuf, input_netif)
#define | LWIP_HOOK_IP4_ROUTE()
#define | LWIP_HOOK_IP4_ROUTE_SRC(src, dest)
#define | LWIP_HOOK_IP4_CANFORWARD(src, dest)
#define | LWIP_HOOK_ETHARP_GET_GW(netif, dest)
#define | LWIP_HOOK_IP6_INPUT(pbuf, input_netif)
#define | LWIP_HOOK_IP6_ROUTE(src, dest)
#define | LWIP_HOOK_ND6_GET_GW(netif, dest)
#define | LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr)
#define | LWIP_HOOK_VLAN_SET(netif, p, src, dst, eth_type)
#define | LWIP_HOOK_MEMP_AVAILABLE(memp_t_type)
#define | LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif)
#define | LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr)
#define | LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, offset)
#define | LWIP_HOOK_DHCP6_APPEND_OPTIONS(netif, dhcp6, state, msg, msg_type, options_len_ptr, max_len)
#define | LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err)
#define | LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err)
#define | LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, addrtype, err)

## Detailed Description

Hooks are undefined by default, define them to a function if you need them.

## Macro Definition Documentation

## LWIP_HOOK_DHCP6_APPEND_OPTIONS

#define LWIP_HOOK_DHCP6_APPEND_OPTIONS | ( |  | netif,
|  |  | dhcp6,
|  |  | state,
|  |  | msg,
|  |  | msg_type,
|  |  | options_len_ptr,
|  |  | max_len
| ) |  |

LWIP_HOOK_DHCP6_APPEND_OPTIONS(netif, dhcp6, state, msg, msg_type, options_len_ptr, max_len): Called from various dhcp6 functions when sending a DHCP6 message. This hook is called just before the DHCP6 message is sent, so the options are at the end of a DHCP6 message. Signature:

void my_hook(struct netif *netif, struct dhcp6 *dhcp, u8_t state, struct dhcp6_msg *msg,
u8_t msg_type, u16_t *options_len_ptr);

Arguments:

- netif: struct netif that the packet will be sent through
- dhcp6: struct dhcp6 on that netif
- state: current dhcp6 state (dhcp6_state_enum_t as an u8_t)
- msg: struct dhcp6_msg that will be sent
- msg_type: dhcp6 message type to be sent (u8_t)
- options_len_ptr: pointer to the current length of options in the dhcp6_msg "msg" (must be increased when options are added!)

Options need to appended like this: u8_t *options = (u8_t *)(msg + 1); LWIP_ASSERT("dhcp option overflow", sizeof(struct dhcp6_msg) + *options_len_ptr + newoptlen <= max_len); options[(*options_len_ptr)++] = <option_data>; [...]

## LWIP_HOOK_DHCP_APPEND_OPTIONS

#define LWIP_HOOK_DHCP_APPEND_OPTIONS | ( |  | netif,
|  |  | dhcp,
|  |  | state,
|  |  | msg,
|  |  | msg_type,
|  |  | options_len_ptr
| ) |  |

LWIP_HOOK_DHCP_APPEND_OPTIONS(netif, dhcp, state, msg, msg_type, options_len_ptr): Called from various dhcp functions when sending a DHCP message. This hook is called just before the DHCP message trailer is added, so the options are at the end of a DHCP message. Signature:

void my_hook(struct netif *netif, struct dhcp *dhcp, u8_t state, struct dhcp_msg *msg,
u8_t msg_type, u16_t *options_len_ptr);

Arguments:

- netif: struct netif that the packet will be sent through
- dhcp: struct dhcp on that netif
- state: current dhcp state (dhcp_state_enum_t as an u8_t)
- msg: struct dhcp_msg that will be sent
- msg_type: dhcp message type to be sent (u8_t)
- options_len_ptr: pointer to the current length of options in the dhcp_msg "msg" (must be increased when options are added!)

Options need to appended like this: LWIP_ASSERT("dhcp option overflow", *options_len_ptr + option_len + 2 <= DHCP_OPTIONS_LEN); msg->options[(*options_len_ptr)++] = <option_number>; msg->options[(*options_len_ptr)++] = <option_len>; msg->options[(*options_len_ptr)++] = <option_bytes>; [...]

## LWIP_HOOK_DHCP_PARSE_OPTION

#define LWIP_HOOK_DHCP_PARSE_OPTION | ( |  | netif,
|  |  | dhcp,
|  |  | state,
|  |  | msg,
|  |  | msg_type,
|  |  | option,
|  |  | len,
|  |  | pbuf,
|  |  | offset
| ) |  |

LWIP_HOOK_DHCP_PARSE_OPTION(netif, dhcp, state, msg, msg_type, option, len, pbuf, option_value_offset): Called from dhcp_parse_reply when receiving a DHCP message. This hook is called for every option in the received message that is not handled internally. Signature:

void my_hook(struct netif *netif, struct dhcp *dhcp, u8_t state, struct dhcp_msg *msg,
u8_t msg_type, u8_t option, u8_t option_len, struct pbuf *pbuf, u16_t option_value_offset);

Arguments:

- netif: struct netif that the packet will be sent through
- dhcp: struct dhcp on that netif
- state: current dhcp state (dhcp_state_enum_t as an u8_t)
- msg: struct dhcp_msg that was received
- msg_type: dhcp message type received (u8_t, ATTENTION: only valid after the message type option has been parsed!)
- option: option value (u8_t)
- len: option data length (u8_t)
- pbuf: pbuf where option data is contained
- option_value_offset: offset in pbuf where option data begins

A nice way to get the option contents is pbuf_get_contiguous(): u8_t buf[32]; u8_t ptr = (u8_t)pbuf_get_contiguous(p, buf, sizeof(buf), LWIP_MIN(option_len, sizeof(buf)), offset);

## LWIP_HOOK_ETHARP_GET_GW

#define LWIP_HOOK_ETHARP_GET_GW | ( |  | netif,
|  |  | dest
| ) |  |

LWIP_HOOK_ETHARP_GET_GW(netif, dest): Called from etharp_output() (IPv4) Signature:

const ip4_addr_t *my_hook(struct netif *netif, const ip4_addr_t *dest);

Arguments:

- netif: the netif used for sending
- dest: the destination IPv4 address Return values:
- the IPv4 address of the gateway to handle the specified destination IPv4 address
- NULL, in which case the netif's default gateway is used

The returned address MUST be directly reachable on the specified netif! This function is meant to implement advanced IPv4 routing together with LWIP_HOOK_IP4_ROUTE(). The actual routing/gateway table implementation is not part of lwIP but can e.g. be hidden in the netif's state argument.

## LWIP_HOOK_FILENAME

#define LWIP_HOOK_FILENAME "path/to/my/lwip_hooks.h"

LWIP_HOOK_FILENAME: Custom filename to #include in files that provide hooks. Declare your hook function prototypes in there, you may also #include all headers providing data types that are need in this file.

## LWIP_HOOK_IP4_CANFORWARD

#define LWIP_HOOK_IP4_CANFORWARD | ( |  | src,
|  |  | dest
| ) |  |

LWIP_HOOK_IP4_CANFORWARD(src, dest): Check if an IPv4 can be forwarded - called from: ip4_input() -> ip4_forward() -> ip4_canforward() (IPv4)

- source address is available via ip4_current_src_addr()
- calling an output function in this context (e.g. multicast router) is allowed Signature:
  int my_hook(struct pbuf *p, u32_t dest_addr_hostorder);
  Arguments:
- p: packet to forward
- dest: destination IPv4 address Returns values:
- 1: forward
- 0: don't forward
- -1: no decision. In that case, ip4_canforward() continues as normal.

## LWIP_HOOK_IP4_INPUT

#define LWIP_HOOK_IP4_INPUT | ( |  | pbuf,
|  |  | input_netif
| ) |  |

LWIP_HOOK_IP4_INPUT(pbuf, input_netif): Called from ip_input() (IPv4) Signature:

int my_hook(struct pbuf *pbuf, struct netif *input_netif);

Arguments:

- pbuf: received struct pbuf passed to ip_input()
- input_netif: struct netif on which the packet has been received Return values:
- 0: Hook has not consumed the packet, packet is processed as normal
- != 0: Hook has consumed the packet. If the hook consumed the packet, 'pbuf' is in the responsibility of the hook (i.e. free it when done).

## LWIP_HOOK_IP4_ROUTE

#define LWIP_HOOK_IP4_ROUTE | ( |  | ) |

LWIP_HOOK_IP4_ROUTE(dest): Called from ip_route() (IPv4) Signature:

struct netif *my_hook(const ip4_addr_t *dest);

Arguments:

- dest: destination IPv4 address Returns values:
- the destination netif
- NULL if no destination netif is found. In that case, ip_route() continues as normal.

## LWIP_HOOK_IP4_ROUTE_SRC

#define LWIP_HOOK_IP4_ROUTE_SRC | ( |  | src,
|  |  | dest
| ) |  |

LWIP_HOOK_IP4_ROUTE_SRC(src, dest): Source-based routing for IPv4 - called from ip_route() (IPv4) Signature:

struct netif *my_hook(const ip4_addr_t *src, const ip4_addr_t *dest);

Arguments:

- src: local/source IPv4 address
- dest: destination IPv4 address Returns values:
- the destination netif
- NULL if no destination netif is found. In that case, ip_route() continues as normal.

## LWIP_HOOK_IP6_INPUT

#define LWIP_HOOK_IP6_INPUT | ( |  | pbuf,
|  |  | input_netif
| ) |  |

LWIP_HOOK_IP6_INPUT(pbuf, input_netif): Called from ip6_input() (IPv6) Signature:

int my_hook(struct pbuf *pbuf, struct netif *input_netif);

Arguments:

- pbuf: received struct pbuf passed to ip6_input()
- input_netif: struct netif on which the packet has been received Return values:
- 0: Hook has not consumed the packet, packet is processed as normal
- != 0: Hook has consumed the packet. If the hook consumed the packet, 'pbuf' is in the responsibility of the hook (i.e. free it when done).

## LWIP_HOOK_IP6_ROUTE

#define LWIP_HOOK_IP6_ROUTE | ( |  | src,
|  |  | dest
| ) |  |

LWIP_HOOK_IP6_ROUTE(src, dest): Called from ip_route() (IPv6) Signature:

struct netif *my_hook(const ip6_addr_t *dest, const ip6_addr_t *src);

Arguments:

- src: source IPv6 address
- dest: destination IPv6 address Return values:
- the destination netif
- NULL if no destination netif is found. In that case, ip6_route() continues as normal.

## LWIP_HOOK_MEMP_AVAILABLE

#define LWIP_HOOK_MEMP_AVAILABLE | ( |  | memp_t_type | ) |

LWIP_HOOK_MEMP_AVAILABLE(memp_t_type): Called from memp_free() when a memp pool was empty and an item is now available Signature:

void my_hook(memp_t type);

## LWIP_HOOK_ND6_GET_GW

#define LWIP_HOOK_ND6_GET_GW | ( |  | netif,
|  |  | dest
| ) |  |

LWIP_HOOK_ND6_GET_GW(netif, dest): Called from nd6_get_next_hop_entry() (IPv6) Signature:

const ip6_addr_t *my_hook(struct netif *netif, const ip6_addr_t *dest);

Arguments:

- netif: the netif used for sending
- dest: the destination IPv6 address Return values:
- the IPv6 address of the next hop to handle the specified destination IPv6 address
- NULL, in which case a NDP-discovered router is used instead

The returned address MUST be directly reachable on the specified netif! This function is meant to implement advanced IPv6 routing together with LWIP_HOOK_IP6_ROUTE(). The actual routing/gateway table implementation is not part of lwIP but can e.g. be hidden in the netif's state argument.

## LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE

#define LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE | ( |  | name,
|  |  | addr,
|  |  | addrtype,
|  |  | err
| ) |  |

LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE(name, addr, addrtype, err) Called from netconn APIs (not usable with callback apps) allowing an external DNS resolver (which uses sequential API) to handle the query. Signature:

int my_hook(const char *name, ip_addr_t *addr, u8_t addrtype, err_t *err)

Arguments:

- name: hostname to resolve
- addr: output host address
- addrtype: type of address to query
- err: output error Return values:
- 0: Hook has not consumed hostname query, query continues into DNS module
- != 0: Hook has consumed the query

err must also be checked to determine if the hook consumed the query, but the query failed

## LWIP_HOOK_SOCKETS_GETSOCKOPT

#define LWIP_HOOK_SOCKETS_GETSOCKOPT | ( |  | s,
|  |  | sock,
|  |  | level,
|  |  | optname,
|  |  | optval,
|  |  | optlen,
|  |  | err
| ) |  |

LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err) Called from socket API to implement getsockopt() for options not provided by lwIP. Core lock is held when this hook is called. Signature:

int my_hook(int s, struct lwip_sock *sock, int level, int optname, void *optval, socklen_t *optlen, int *err)

Arguments:

- s: socket file descriptor
- sock: internal socket descriptor (see lwip/priv/sockets_priv.h)
- level: protocol level at which the option resides
- optname: option to get
- optval: value to get
- optlen: size of optval
- err: output error Return values:
- 0: Hook has not consumed the option, code continues as normal (to internal options)
- != 0: Hook has consumed the option, 'err' is returned

## LWIP_HOOK_SOCKETS_SETSOCKOPT

#define LWIP_HOOK_SOCKETS_SETSOCKOPT | ( |  | s,
|  |  | sock,
|  |  | level,
|  |  | optname,
|  |  | optval,
|  |  | optlen,
|  |  | err
| ) |  |

LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) Called from socket API to implement setsockopt() for options not provided by lwIP. Core lock is held when this hook is called. Signature:

int my_hook(int s, struct lwip_sock *sock, int level, int optname, const void *optval, socklen_t optlen, int *err)

Arguments:

- s: socket file descriptor
- sock: internal socket descriptor (see lwip/priv/sockets_priv.h)
- level: protocol level at which the option resides
- optname: option to set
- optval: value to set
- optlen: size of optval
- err: output error Return values:
- 0: Hook has not consumed the option, code continues as normal (to internal options)
- != 0: Hook has consumed the option, 'err' is returned

## LWIP_HOOK_TCP_INPACKET_PCB

#define LWIP_HOOK_TCP_INPACKET_PCB | ( |  | pcb,
|  |  | hdr,
|  |  | optlen,
|  |  | opt1len,
|  |  | opt2,
|  |  | p
| ) |  |

LWIP_HOOK_TCP_INPACKET_PCB: Hook for intercepting incoming packets before they are passed to a pcb. This allows updating some state or even dropping a packet. Signature:

err_t my_hook_tcp_inpkt(struct tcp_pcb *pcb, struct tcp_hdr *hdr, u16_t optlen, u16_t opt1len, u8_t *opt2, struct pbuf *p);

Arguments:

- pcb: tcp_pcb selected for input of this packet (ATTENTION: this may be struct tcp_pcb_listen if pcb->state == LISTEN)
- hdr: pointer to tcp header (ATTENTION: tcp options may not be in one piece!)
- optlen: tcp option length
- opt1len: tcp option length 1st part
- opt2: if this is != NULL, tcp options are split among 2 pbufs. In that case, options start at right after the tcp header ('(u8_t*)(hdr + 1)') for the first 'opt1len' bytes and the rest starts at 'opt2'. opt2len can be simply calculated: 'opt2len = optlen - opt1len;'
- p: input packet, p->payload points to application data (that's why tcp hdr and options are passed in separately) Return value:
- ERR_OK: continue input of this packet as normal
- != ERR_OK: drop this packet for input (don't continue input processing)

ATTENTION: don't call any tcp api functions that might change tcp state (pcb state or any pcb lists) from this callback!

## LWIP_HOOK_TCP_ISN

#define LWIP_HOOK_TCP_ISN | ( |  | local_ip,
|  |  | local_port,
|  |  | remote_ip,
|  |  | remote_port
| ) |  |

LWIP_HOOK_TCP_ISN: Hook for generation of the Initial Sequence Number (ISN) for a new TCP connection. The default lwIP ISN generation algorithm is very basic and may allow for TCP spoofing attacks. This hook provides the means to implement the standardized ISN generation algorithm from RFC 6528 (see contrib/adons/tcp_isn), or any other desired algorithm as a replacement. Called from tcp_connect() and tcp_listen_input() when an ISN is needed for a new TCP connection, if TCP support (LWIP_TCP) is enabled.
Signature:

u32_t my_hook_tcp_isn(const ip_addr_t* local_ip, u16_t local_port, const ip_addr_t* remote_ip, u16_t remote_port);

- it may be necessary to use "struct ip_addr" (ip4_addr, ip6_addr) instead of "ip_addr_t" in function declarations
  Arguments:
- local_ip: pointer to the local IP address of the connection
- local_port: local port number of the connection (host-byte order)
- remote_ip: pointer to the remote IP address of the connection
- remote_port: remote port number of the connection (host-byte order)
  Return value:
- the 32-bit Initial Sequence Number to use for the new TCP connection.

## LWIP_HOOK_TCP_OUT_ADD_TCPOPTS

#define LWIP_HOOK_TCP_OUT_ADD_TCPOPTS | ( |  | p,
|  |  | hdr,
|  |  | pcb,
|  |  | opts
| ) |  |

LWIP_HOOK_TCP_OUT_ADD_TCPOPTS: Hook for adding custom options to outgoing tcp segments. Space for these custom options has to be reserved via LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH. Signature:

u32_t *my_hook_tcp_out_add_tcpopts(struct pbuf *p, struct tcp_hdr *hdr, const struct tcp_pcb *pcb, u32_t *opts);

Arguments:

- p: output packet, p->payload pointing to tcp header, data follows
- hdr: tcp header
- pcb: tcp_pcb that transmits (ATTENTION: this may be NULL or struct tcp_pcb_listen if pcb->state == LISTEN)
- opts: pointer where to add the custom options (there may already be options between the header and these) Return value:
- pointer pointing directly after the inserted options

ATTENTION: don't call any tcp api functions that might change tcp state (pcb state or any pcb lists) from this callback!

## LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH

#define LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH | ( |  | pcb,
|  |  | internal_len
| ) |  |

LWIP_HOOK_TCP_OUT_TCPOPT_LENGTH: Hook for increasing the size of the options allocated with a tcp header. Together with LWIP_HOOK_TCP_OUT_ADD_TCPOPTS, this can be used to add custom options to outgoing tcp segments. Signature:

u8_t my_hook_tcp_out_tcpopt_length(const struct tcp_pcb *pcb, u8_t internal_option_length);

Arguments:

- pcb: tcp_pcb that transmits (ATTENTION: this may be NULL or struct tcp_pcb_listen if pcb->state == LISTEN)
- internal_option_length: tcp option length used by the stack internally Return value:
- a number of bytes to allocate for tcp options (internal_option_length <= ret <= 40)

ATTENTION: don't call any tcp api functions that might change tcp state (pcb state or any pcb lists) from this callback!

## LWIP_HOOK_UNKNOWN_ETH_PROTOCOL

#define LWIP_HOOK_UNKNOWN_ETH_PROTOCOL | ( |  | pbuf,
|  |  | netif
| ) |  |

LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(pbuf, netif): Called from ethernet_input() when an unknown eth type is encountered. Signature:

err_t my_hook(struct pbuf* pbuf, struct netif* netif);

Arguments:

- p: rx packet with unknown eth type
- netif: netif on which the packet has been received Return values:
- ERR_OK if packet is accepted (hook function now owns the pbuf)
- any error code otherwise (pbuf is freed)

Payload points to ethernet header!

## LWIP_HOOK_VLAN_CHECK

#define LWIP_HOOK_VLAN_CHECK | ( |  | netif,
|  |  | eth_hdr,
|  |  | vlan_hdr
| ) |  |

LWIP_HOOK_VLAN_CHECK(netif, eth_hdr, vlan_hdr): Called from ethernet_input() if VLAN support is enabled Signature:

int my_hook(struct netif *netif, struct eth_hdr *eth_hdr, struct eth_vlan_hdr *vlan_hdr);

Arguments:

- netif: struct netif on which the packet has been received
- eth_hdr: struct eth_hdr of the packet
- vlan_hdr: struct eth_vlan_hdr of the packet Return values:
- 0: Packet must be dropped.
- != 0: Packet must be accepted.

## LWIP_HOOK_VLAN_SET

#define LWIP_HOOK_VLAN_SET | ( |  | netif,
|  |  | p,
|  |  | src,
|  |  | dst,
|  |  | eth_type
| ) |  |

LWIP_HOOK_VLAN_SET: Hook can be used to set prio_vid field of vlan_hdr. If you need to store data on per-netif basis to implement this callback, see Client data handling. Called from ethernet_output() if VLAN support (ETHARP_SUPPORT_VLAN) is enabled.
Signature:

s32_t my_hook_vlan_set(struct netif* netif, struct pbuf* pbuf, const struct eth_addr* src, const struct eth_addr* dst, u16_t eth_type);

Arguments:

- netif: struct netif that the packet will be sent through
- p: struct pbuf packet to be sent
- src: source eth address
- dst: destination eth address
- eth_type: ethernet type to packet to be sent

Return values:

- <0: Packet shall not contain VLAN header.
- 0 <= return value <= 0xFFFF: Packet shall contain VLAN header. Return value is prio_vid in host byte order.

lwip_sock
Definition: sockets_priv.h:67
ip_addr
Definition: ip_addr.h:69
dhcp6_msg
Definition: dhcp6.h:59
dhcp_msg
Definition: dhcp.h:64
netif::state
void * state
Definition: netif.h:332
ip6_addr
Definition: ip6_addr.h:59
eth_hdr
Definition: ethernet.h:76
netif
Definition: netif.h:269
netif::name
char name[2]
Definition: netif.h:356
tcp_pcb
Definition: tcp.h:242
err_t
s8_t err_t
Definition: err.h:96
eth_addr
Definition: ethernet.h:60
memp_t
memp_t
Definition: memp.h:52
eth_vlan_hdr
Definition: ethernet.h:98
pbuf
Definition: pbuf.h:186
ip4_addr
Definition: ip4_addr.h:51