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->offset == 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->len = in_len;
83 			}
84 		} else {
85 			opaque->len = in_len;
86 		}
87 	}
88 
89 	return lwm2m_engine_get_opaque_more(in, value, buflen,
90 					    opaque, last_block);
91 }
92 
put_opaque(struct lwm2m_output_context * out,struct lwm2m_obj_path * path,char * buf,size_t buflen)93 static int put_opaque(struct lwm2m_output_context *out,
94 			  struct lwm2m_obj_path *path, char *buf,
95 			  size_t buflen)
96 {
97 	int ret;
98 
99 	ret = buf_append(CPKT_BUF_WRITE(out->out_cpkt), buf, buflen);
100 	if (ret < 0) {
101 		return ret;
102 	}
103 
104 	return buflen;
105 }
106 
107 
108 const struct lwm2m_writer opaque_writer = {
109 	.put_opaque = put_opaque,
110 };
111 
112 const struct lwm2m_reader opaque_reader = {
113 	.get_opaque = get_opaque,
114 };
115 
do_read_op_opaque(struct lwm2m_message * msg,int content_format)116 int do_read_op_opaque(struct lwm2m_message *msg, int content_format)
117 {
118 	/* Opaque can only return single resource (instance) */
119 	if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
120 		return -EPERM;
121 	} else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE) {
122 		if (!IS_ENABLED(CONFIG_LWM2M_VERSION_1_1)) {
123 			return -ENOENT;
124 		} else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE_INST) {
125 			return -ENOENT;
126 		}
127 	}
128 
129 	return lwm2m_perform_read_op(msg, content_format);
130 }
131 
do_write_op_opaque(struct lwm2m_message * msg)132 int do_write_op_opaque(struct lwm2m_message *msg)
133 {
134 	struct lwm2m_engine_obj_inst *obj_inst = NULL;
135 	struct lwm2m_engine_obj_field *obj_field;
136 	struct lwm2m_engine_res *res = NULL;
137 	struct lwm2m_engine_res_inst *res_inst = NULL;
138 	int ret;
139 	uint8_t created = 0U;
140 
141 	ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
142 	if (ret < 0) {
143 		return ret;
144 	}
145 
146 	ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
147 	if (ret < 0) {
148 		return ret;
149 	}
150 
151 	ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
152 	if (ret < 0) {
153 		return -ENOENT;
154 	}
155 
156 	if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
157 		msg->path.level = LWM2M_PATH_LEVEL_RESOURCE;
158 	}
159 
160 	return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
161 }
162