1 /*
2 * Copyright (c) 2023 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * Copyright (c) 2015, Yanzi Networks AB.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the copyright holder nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
34 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #define LOG_MODULE_NAME net_lwm2m_opaque
38 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
39
40 #include <zephyr/logging/log.h>
41 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
42
43 #include <stdarg.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
48
49 #include "lwm2m_object.h"
50 #include "lwm2m_rw_opaque.h"
51 #include "lwm2m_engine.h"
52 #include "lwm2m_util.h"
53
get_opaque(struct lwm2m_input_context * in,uint8_t * value,size_t buflen,struct lwm2m_opaque_context * opaque,bool * last_block)54 static int get_opaque(struct lwm2m_input_context *in, uint8_t *value,
55 size_t buflen, struct lwm2m_opaque_context *opaque,
56 bool *last_block)
57 {
58 uint16_t in_len;
59
60 if (opaque->remaining == 0) {
61 coap_packet_get_payload(in->in_cpkt, &in_len);
62
63 if (in_len == 0) {
64 return -ENODATA;
65 }
66
67 if (in->block_ctx != NULL) {
68 uint32_t block_num =
69 in->block_ctx->ctx.current /
70 coap_block_size_to_bytes(
71 in->block_ctx->ctx.block_size);
72
73 if (block_num == 0) {
74 opaque->len = in->block_ctx->ctx.total_size;
75 }
76
77 if (opaque->len == 0) {
78 /* No size1 option provided, use current
79 * payload size. This will reset on next packet
80 * received.
81 */
82 opaque->remaining = in_len;
83 } else {
84 opaque->remaining = opaque->len;
85 }
86
87 } else {
88 opaque->len = in_len;
89 opaque->remaining = in_len;
90 }
91 }
92
93 return lwm2m_engine_get_opaque_more(in, value, buflen,
94 opaque, last_block);
95 }
96
put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)97 static int put_opaque(struct lwm2m_output_context *out,
98 struct lwm2m_obj_path *path, char *buf,
99 size_t buflen)
100 {
101 int ret;
102
103 ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, buflen);
104 if (ret < 0) {
105 return ret;
106 }
107
108 return buflen;
109 }
110
111
112 const struct lwm2m_writer opaque_writer = {
113 .put_opaque = put_opaque,
114 };
115
116 const struct lwm2m_reader opaque_reader = {
117 .get_opaque = get_opaque,
118 };
119
do_read_op_opaque(struct lwm2m_message * msg,int content_format)120 int do_read_op_opaque(struct lwm2m_message *msg, int content_format)
121 {
122 /* Opaque can only return single resource (instance) */
123 if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
124 return -EPERM;
125 } else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE) {
126 if (!IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
127 return -ENOENT;
128 } else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE_INST) {
129 return -ENOENT;
130 }
131 }
132
133 return lwm2m_perform_read_op(msg, content_format);
134 }
135
do_write_op_opaque(struct lwm2m_message * msg)136 int do_write_op_opaque(struct lwm2m_message *msg)
137 {
138 struct lwm2m_engine_obj_inst *obj_inst = NULL;
139 struct lwm2m_engine_obj_field *obj_field;
140 struct lwm2m_engine_res *res = NULL;
141 struct lwm2m_engine_res_inst *res_inst = NULL;
142 int ret;
143 uint8_t created = 0U;
144
145 ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
146 if (ret < 0) {
147 return ret;
148 }
149
150 ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
151 if (ret < 0) {
152 return ret;
153 }
154
155 ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
156 if (ret < 0) {
157 return -ENOENT;
158 }
159
160 if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
161 msg->path.level = LWM2M_PATH_LEVEL_RESOURCE;
162 }
163
164 return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
165 }
166