blob: a98d5d4b2d4989bb1b0791a890288dac9cf4be3f [file] [log] [blame]
James Kuszmaul871d0712021-01-17 11:30:43 -08001/**
2 * @file re_pcp.h PCP - Port Control Protocol (RFC 6887)
3 *
4 * Copyright (C) 2010 - 2014 Creytiv.com
5 */
6
7
8/*
9 * The following specifications are implemented:
10 *
11 * RFC 6887
12 * draft-ietf-pcp-description-option-02
13 * draft-cheshire-pcp-unsupp-family
14 *
15 */
16
17
18/** PCP Version numbers */
19enum {
20 PCP_VERSION = 2,
21};
22
23/* PCP port numbers */
24enum {
25 PCP_PORT_CLI = 5350, /* for ANNOUNCE notifications */
26 PCP_PORT_SRV = 5351,
27};
28
29/** PCP Protocol sizes */
30enum {
31 PCP_HDR_SZ = 24,
32 PCP_NONCE_SZ = 12,
33 PCP_MAP_SZ = 36,
34 PCP_PEER_SZ = 56,
35
36 PCP_MIN_PACKET = 24,
37 PCP_MAX_PACKET = 1100
38};
39
40enum pcp_opcode {
41 PCP_ANNOUNCE = 0,
42 PCP_MAP = 1,
43 PCP_PEER = 2,
44};
45
46enum pcp_result {
47 PCP_SUCCESS = 0,
48 PCP_UNSUPP_VERSION = 1,
49 PCP_NOT_AUTHORIZED = 2,
50 PCP_MALFORMED_REQUEST = 3,
51 PCP_UNSUPP_OPCODE = 4,
52 PCP_UNSUPP_OPTION = 5,
53 PCP_MALFORMED_OPTION = 6,
54 PCP_NETWORK_FAILURE = 7,
55 PCP_NO_RESOURCES = 8,
56 PCP_UNSUPP_PROTOCOL = 9,
57 PCP_USER_EX_QUOTA = 10,
58 PCP_CANNOT_PROVIDE_EXTERNAL = 11,
59 PCP_ADDRESS_MISMATCH = 12,
60 PCP_EXCESSIVE_REMOTE_PEERS = 13,
61 PCP_UNSUPP_FAMILY = 14 /*draft-cheshire-pcp-unsupp-family*/
62};
63
64enum pcp_option_code {
65 PCP_OPTION_THIRD_PARTY = 1,
66 PCP_OPTION_PREFER_FAILURE = 2,
67 PCP_OPTION_FILTER = 3,
68 PCP_OPTION_DESCRIPTION = 128, /* RFC 7220 */
69};
70
71/* forward declarations */
72struct udp_sock;
73
74/** Defines a PCP option */
75struct pcp_option {
76 struct le le;
77 enum pcp_option_code code;
78 union {
79 struct sa third_party; /* Internal IP-address */
80 struct pcp_option_filter {
81 uint8_t prefix_length;
82 struct sa remote_peer;
83 } filter;
84 char *description;
85 } u;
86};
87
88/**
89 * Defines a complete and decoded PCP request/response.
90 *
91 * A PCP message consist of a header, and optional payload and options:
92 *
93 * [ Header ]
94 * ( Opcode Payload )
95 * ( PCP Options )
96 *
97 */
98struct pcp_msg {
99
100 /** PCP Common Header */
101 struct pcp_hdr {
102 uint8_t version; /**< PCP Protocol version 2 */
103 unsigned resp:1; /**< R-bit; 0=Request, 1=Response */
104 uint8_t opcode; /**< A 7-bit opcode */
105 uint32_t lifetime; /**< Lifetime in [seconds] */
106
107 /* request: */
108 struct sa cli_addr; /**< Client's IP Address (SA_ADDR) */
109
110 /* response: */
111 enum pcp_result result; /**< Result code for this response */
112 uint32_t epoch; /**< Server's Epoch Time [seconds] */
113 } hdr;
114
115 /** PCP Opcode-specific payload */
116 union pcp_payload {
117 struct pcp_map {
118 uint8_t nonce[PCP_NONCE_SZ]; /**< Mapping Nonce */
119 uint8_t proto; /**< IANA protocol */
120 uint16_t int_port; /**< Internal Port */
121 struct sa ext_addr; /**< External Address */
122 } map;
123 struct pcp_peer {
124 struct pcp_map map; /**< Common with MAP */
125 struct sa remote_addr; /**< Remote address */
126 } peer;
127 } pld;
128
129 /** List of PCP Options (struct pcp_option) */
130 struct list optionl;
131};
132
133/** PCP request configuration */
134struct pcp_conf {
135 uint32_t irt; /**< Initial retransmission time [seconds] */
136 uint32_t mrc; /**< Maximum retransmission count */
137 uint32_t mrt; /**< Maximum retransmission time [seconds] */
138 uint32_t mrd; /**< Maximum retransmission duration [seconds] */
139};
140
141
142/* request */
143
144struct pcp_request;
145
146typedef void (pcp_resp_h)(int err, struct pcp_msg *msg, void *arg);
147
148int pcp_request(struct pcp_request **reqp, const struct pcp_conf *conf,
149 const struct sa *pcp_server, enum pcp_opcode opcode,
150 uint32_t lifetime, const void *payload,
151 pcp_resp_h *resph, void *arg, uint32_t optionc, ...);
152void pcp_force_refresh(struct pcp_request *req);
153
154
155/* reply */
156
157int pcp_reply(struct udp_sock *us, const struct sa *dst, struct mbuf *req,
158 enum pcp_opcode opcode, enum pcp_result result,
159 uint32_t lifetime, uint32_t epoch_time, const void *payload);
160
161
162/* msg */
163
164typedef bool (pcp_option_h)(const struct pcp_option *opt, void *arg);
165
166int pcp_msg_decode(struct pcp_msg **msgp, struct mbuf *mb);
167int pcp_msg_printhdr(struct re_printf *pf, const struct pcp_msg *msg);
168int pcp_msg_print(struct re_printf *pf, const struct pcp_msg *msg);
169struct pcp_option *pcp_msg_option(const struct pcp_msg *msg,
170 enum pcp_option_code code);
171struct pcp_option *pcp_msg_option_apply(const struct pcp_msg *msg,
172 pcp_option_h *h, void *arg);
173const void *pcp_msg_payload(const struct pcp_msg *msg);
174
175
176/* option */
177
178int pcp_option_encode(struct mbuf *mb, enum pcp_option_code code,
179 const void *v);
180int pcp_option_decode(struct pcp_option **optp, struct mbuf *mb);
181int pcp_option_print(struct re_printf *pf, const struct pcp_option *opt);
182
183
184/* encode */
185
186int pcp_msg_req_vencode(struct mbuf *mb, enum pcp_opcode opcode,
187 uint32_t lifetime, const struct sa *cli_addr,
188 const void *payload, uint32_t optionc, va_list ap);
189int pcp_msg_req_encode(struct mbuf *mb, enum pcp_opcode opcode,
190 uint32_t lifetime, const struct sa *cli_addr,
191 const void *payload, uint32_t optionc, ...);
192
193
194/* pcp */
195
196int pcp_ipaddr_encode(struct mbuf *mb, const struct sa *sa);
197int pcp_ipaddr_decode(struct mbuf *mb, struct sa *sa);
198const char *pcp_result_name(enum pcp_result result);
199const char *pcp_opcode_name(enum pcp_opcode opcode);
200const char *pcp_proto_name(int proto);