summaryrefslogtreecommitdiff
path: root/libdhcp/dhcp_common.c
blob: d69183669ecddbddb678ea3892cccfb70ecb9878 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* libdhcp/dhcp_common.c - Base definitions for the DHCP protocol
 *
 * Copyright (C) 2025  Luke T. Shumaker <lukeshu@lukeshu.com>
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

#include "dhcp_common.h"

/**
 * DHCP Options
 * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options
 */
bool dhcp_opt_length_is_valid(uint8_t opt, uint16_t len) {
	switch (opt) {
	/* RFC 2132 */
	case DHCP_OPT_PAD:               return len == 0;
	case DHCP_OPT_SUBNET_MASK:       return len == 4;
	case DHCP_OPT_TIME_OFFSET:       return len == 4;
	case DHCP_OPT_ROUTER:            return len >= 4 && len % 4 == 0;
	case DHCP_OPT_TIME_SERVER:       return len >= 4 && len % 4 == 0;
	case DHCP_OPT_NAME_SERVER:       return len >= 4 && len % 4 == 0;
	case DHCP_OPT_DOMAIN_SERVER:     return len >= 4 && len % 4 == 0;
	case DHCP_OPT_LOG_SERVER:        return len >= 4 && len % 4 == 0;
	case DHCP_OPT_QUOTES_SERVER:     return len >= 4 && len % 4 == 0;
	case DHCP_OPT_LPR_SERVER:        return len >= 4 && len % 4 == 0;
	case DHCP_OPT_IMPRESS_SERVER:    return len >= 4 && len % 4 == 0;
	case DHCP_OPT_RLP_SERVER:        return len >= 4 && len % 4 == 0;
	case DHCP_OPT_HOSTNAME:          return len >= 1;
	case DHCP_OPT_BOOT_FILE_SIZE:    return len == 2;
	case DHCP_OPT_MERIT_DUMP_FILE:   return len >= 1;
	case DHCP_OPT_DOMAIN_NAME:       return len >= 1;
	case DHCP_OPT_SWAP_SERVER:       return len == 4; /* IANA says length is "N", but RFC 2132 says "length is 4"; likely releated to errata ID 487 */
	case DHCP_OPT_ROOT_PATH:         return len >= 1;
	case DHCP_OPT_EXTENSION_FILE:    return len >= 1;
	case DHCP_OPT_FORWARD_ONOFF:     return len == 1;
	case DHCP_OPT_SRCRTE_ONOFF:      return len == 1;
	case DHCP_OPT_POLICY_FILTER:     return len >= 8 && len % 8 == 0;
	case DHCP_OPT_MAX_DG_ASSEMBLY:   return len == 2;
	case DHCP_OPT_DEFAULT_IP_TTL:    return len == 1;
	case DHCP_OPT_MTU_TIMEOUT:       return len == 4;
	case DHCP_OPT_MTU_PLATEAU:       return len >= 2 && len % 2 == 0;
	case DHCP_OPT_MTU_INTERFACE:     return len == 2;
	case DHCP_OPT_MTU_SUBNET:        return len == 1;
	case DHCP_OPT_BROADCAST_ADDRESS: return len == 4;
	case DHCP_OPT_MASK_DISCOVERY:    return len == 1;
	case DHCP_OPT_MASK_SUPPLIER:     return len == 1;
	case DHCP_OPT_ROUTER_DISCOVERY:  return len == 1;
	case DHCP_OPT_ROUTER_REQUEST:    return len == 4;
	case DHCP_OPT_STATIC_ROUTE:      return len >= 8 && len % 8 == 0;
	case DHCP_OPT_TRAILERS:          return len == 1;
	case DHCP_OPT_ARP_TIMEOUT:       return len == 4;
	case DHCP_OPT_ETHERNET:          return len == 1;
	case DHCP_OPT_DEFAULT_TCP_TTL:   return len == 1;
	case DHCP_OPT_KEEPALIVE_TIME:    return len == 4;
	case DHCP_OPT_KEEPALIVE_DATA:    return len == 1;
	case DHCP_OPT_NIS_DOMAIN:        return len >= 1;
	case DHCP_OPT_NIS_SERVERS:       return len >= 4 && len % 4 == 0;
	case DHCP_OPT_NTP_SERVERS:       return len >= 4 && len % 4 == 0;
	case DHCP_OPT_VENDOR_SPECIFIC:   return len >= 1;
	case DHCP_OPT_NETBIOS_NAME_SRV:  return len >= 4 && len % 4 == 0;
	case DHCP_OPT_NETBIOS_DIST_SRV:  return len >= 4 && len % 4 == 0;
	case DHCP_OPT_NETBIOS_NODE_TYPE: return len == 1;
	case DHCP_OPT_NETBIOS_SCOPE:     return len >= 1;
	case DHCP_OPT_X_WINDOW_FONT:     return len >= 4 && len % 4 == 0;
	case DHCP_OPT_X_WINDOW_MANAGER:  return len >= 4 && len % 4 == 0;
	case DHCP_OPT_ADDRESS_REQUEST:   return len == 4;
	case DHCP_OPT_ADDRESS_TIME:      return len == 4;
	case DHCP_OPT_OVERLOAD:          return len == 1;
	case DHCP_OPT_DHCP_MSG_TYPE:     return len == 1;
	case DHCP_OPT_DHCP_SERVER_ID:    return len == 4;
	case DHCP_OPT_PARAMETER_LIST:    return len >= 1;
	case DHCP_OPT_DHCP_MESSAGE:      return len >= 1;
	case DHCP_OPT_DHCP_MAX_MSG_SIZE: return len == 2;
	case DHCP_OPT_RENEWAL_TIME:      return len == 4;
	case DHCP_OPT_REBINDING_TIME:    return len == 4;
	case DHCP_OPT_CLASS_ID:          return len >= 1;
	case DHCP_OPT_CLIENT_ID:         return len >= 2;

	/* RFC 2132 */
	case DHCP_OPT_END:               return len == 0;

	/* Unrecognized */
	default:
		return true;
	}
}

/**
 * DHCP Message Type 53 Values
 * https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#message-type-53
 */
const char *dhcp_msgtyp_str(uint8_t typ) {
	switch (typ) {
	case DHCP_MSGTYP_DISCOVER: return "DHCP_MSGTYP_DISCOVER";
	case DHCP_MSGTYP_OFFER:    return "DHCP_MSGTYP_OFFER";
	case DHCP_MSGTYP_REQUEST:  return "DHCP_MSGTYP_REQUEST";
	case DHCP_MSGTYP_DECLINE:  return "DHCP_MSGTYP_DECLINE";
	case DHCP_MSGTYP_ACK:      return "DHCP_MSGTYP_ACK";
	case DHCP_MSGTYP_NAK:      return "DHCP_MSGTYP_NAK";
	case DHCP_MSGTYP_RELEASE:  return "DHCP_MSGTYP_RELEASE";
	case DHCP_MSGTYP_INFORM:   return "DHCP_MSGTYP_INFORM";
	default:                   return const_byte_str(typ);
	}
}