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