blob: 264dcbb04222a90ec7e1569b3b0a77eef35c444b [file] [log] [blame]
James Kuszmaul871d0712021-01-17 11:30:43 -08001/**
2 * @file pcp/reply.c PCP reply
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <re_types.h>
7#include <re_fmt.h>
8#include <re_mem.h>
9#include <re_mbuf.h>
10#include <re_list.h>
11#include <re_sa.h>
12#include <re_udp.h>
13#include <re_pcp.h>
14#include "pcp.h"
15
16
17static int pcp_header_encode_response(struct mbuf *mb, enum pcp_opcode opcode,
18 enum pcp_result result,
19 uint32_t lifetime, uint32_t epoch_time)
20{
21 int err = 0;
22
23 if (!mb)
24 return EINVAL;
25
26 err |= mbuf_write_u8(mb, PCP_VERSION);
27 err |= mbuf_write_u8(mb, 1<<7 | opcode);
28 err |= mbuf_write_u8(mb, 0x00);
29 err |= mbuf_write_u8(mb, result);
30 err |= mbuf_write_u32(mb, htonl(lifetime));
31 err |= mbuf_write_u32(mb, htonl(epoch_time));
32 err |= mbuf_fill(mb, 0x00, 12);
33
34 return err;
35}
36
37
38/**
39 * Send a PCP response message
40 *
41 * @param us UDP Socket
42 * @param dst Destination network address
43 * @param req Buffer containing original PCP request (optional)
44 * @param opcode PCP opcode
45 * @param result PCP result for the response
46 * @param lifetime Lifetime in [seconds]
47 * @param epoch_time Server Epoch-time
48 * @param payload PCP payload, e.g. struct pcp_map (optional)
49 *
50 * @return 0 if success, otherwise errorcode
51 */
52int pcp_reply(struct udp_sock *us, const struct sa *dst, struct mbuf *req,
53 enum pcp_opcode opcode, enum pcp_result result,
54 uint32_t lifetime, uint32_t epoch_time, const void *payload)
55{
56 struct mbuf *mb;
57 size_t start;
58 int err;
59
60 if (!us || !dst)
61 return EINVAL;
62
63 if (req) {
64 /* the complete Request must be included in the Response */
65 mb = mem_ref(req);
66 }
67 else {
68 mb = mbuf_alloc(128);
69 if (!mb)
70 return ENOMEM;
71 }
72
73 start = mb->pos;
74
75 /* encode the response packet */
76 err = pcp_header_encode_response(mb, opcode, result,
77 lifetime, epoch_time);
78 if (err)
79 goto out;
80
81 if (payload) {
82 err = pcp_payload_encode(mb, opcode, payload);
83 if (err)
84 goto out;
85 }
86
87 mb->pos = start;
88 err = udp_send(us, dst, mb);
89
90 out:
91 mem_deref(mb);
92 return err;
93}