1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2015-2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <logging/log.h>
10 
11 #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
12 LOG_MODULE_REGISTER(ipsp);
13 
14 /* Preventing log module registration in net_core.h */
15 #define NET_LOG_ENABLED	0
16 
17 #include <zephyr.h>
18 #include <linker/sections.h>
19 #include <errno.h>
20 #include <stdio.h>
21 
22 #include <net/net_pkt.h>
23 #include <net/net_if.h>
24 #include <net/net_core.h>
25 #include <net/net_context.h>
26 #include <net/udp.h>
27 
28 /* Define my IP address where to expect messages */
29 #define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
30 			 0, 0, 0, 0, 0, 0, 0, 0x1 } } }
31 #define MY_PREFIX_LEN 64
32 
33 static struct in6_addr in6addr_my = MY_IP6ADDR;
34 
35 #define MY_PORT 4242
36 
37 #define STACKSIZE 2000
38 K_THREAD_STACK_DEFINE(thread_stack, STACKSIZE);
39 static struct k_thread thread_data;
40 
41 static uint8_t buf_tx[NET_IPV6_MTU];
42 
43 #define MAX_DBG_PRINT 64
44 
45 NET_PKT_TX_SLAB_DEFINE(echo_tx_tcp, 15);
46 NET_PKT_DATA_POOL_DEFINE(echo_data_tcp, 30);
47 
tx_tcp_pool(void)48 static struct k_mem_slab *tx_tcp_pool(void)
49 {
50 	return &echo_tx_tcp;
51 }
52 
data_tcp_pool(void)53 static struct net_buf_pool *data_tcp_pool(void)
54 {
55 	return &echo_data_tcp;
56 }
57 
58 static struct k_sem quit_lock;
59 
quit(void)60 static inline void quit(void)
61 {
62 	k_sem_give(&quit_lock);
63 }
64 
init_app(void)65 static inline void init_app(void)
66 {
67 	LOG_INF("Run IPSP sample");
68 
69 	k_sem_init(&quit_lock, 0, K_SEM_MAX_LIMIT);
70 
71 	if (net_addr_pton(AF_INET6,
72 			  CONFIG_NET_CONFIG_MY_IPV6_ADDR,
73 			  &in6addr_my) < 0) {
74 		LOG_ERR("Invalid IPv6 address %s",
75 			CONFIG_NET_CONFIG_MY_IPV6_ADDR);
76 	}
77 
78 	do {
79 		struct net_if_addr *ifaddr;
80 
81 		ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
82 					      &in6addr_my, NET_ADDR_MANUAL, 0);
83 	} while (0);
84 }
85 
get_context(struct net_context ** udp_recv6,struct net_context ** tcp_recv6)86 static inline bool get_context(struct net_context **udp_recv6,
87 			       struct net_context **tcp_recv6)
88 {
89 	int ret;
90 	struct sockaddr_in6 my_addr6 = { 0 };
91 
92 	my_addr6.sin6_family = AF_INET6;
93 	my_addr6.sin6_port = htons(MY_PORT);
94 
95 	ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
96 	if (ret < 0) {
97 		LOG_ERR("Cannot get network context for IPv6 UDP (%d)", ret);
98 		return false;
99 	}
100 
101 	ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
102 			       sizeof(struct sockaddr_in6));
103 	if (ret < 0) {
104 		LOG_ERR("Cannot bind IPv6 UDP port %d (%d)",
105 			ntohs(my_addr6.sin6_port), ret);
106 		return false;
107 	}
108 
109 	ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, tcp_recv6);
110 	if (ret < 0) {
111 		LOG_ERR("Cannot get network context for IPv6 TCP (%d)", ret);
112 		return false;
113 	}
114 
115 	net_context_setup_pools(*tcp_recv6, tx_tcp_pool, data_tcp_pool);
116 
117 	ret = net_context_bind(*tcp_recv6, (struct sockaddr *)&my_addr6,
118 			       sizeof(struct sockaddr_in6));
119 	if (ret < 0) {
120 		LOG_ERR("Cannot bind IPv6 TCP port %d (%d)",
121 			ntohs(my_addr6.sin6_port), ret);
122 		return false;
123 	}
124 
125 	ret = net_context_listen(*tcp_recv6, 0);
126 	if (ret < 0) {
127 		LOG_ERR("Cannot listen IPv6 TCP (%d)", ret);
128 		return false;
129 	}
130 
131 	return true;
132 }
133 
build_reply(const char * name,struct net_pkt * pkt,uint8_t * buf)134 static int build_reply(const char *name,
135 		       struct net_pkt *pkt,
136 		       uint8_t *buf)
137 {
138 	int reply_len = net_pkt_remaining_data(pkt);
139 	int ret;
140 
141 	LOG_DBG("%s received %d bytes", log_strdup(name), reply_len);
142 
143 	ret = net_pkt_read(pkt, buf, reply_len);
144 	if (ret < 0) {
145 		LOG_ERR("cannot read packet: %d", ret);
146 		return ret;
147 	}
148 
149 	LOG_DBG("sending %d bytes", reply_len);
150 
151 	return reply_len;
152 }
153 
pkt_sent(struct net_context * context,int status,void * user_data)154 static inline void pkt_sent(struct net_context *context,
155 			    int status,
156 			    void *user_data)
157 {
158 	if (status >= 0) {
159 		LOG_DBG("Sent %d bytes", status);
160 	}
161 }
162 
set_dst_addr(sa_family_t family,struct net_pkt * pkt,struct net_ipv6_hdr * ipv6_hdr,struct net_udp_hdr * udp_hdr,struct sockaddr * dst_addr)163 static inline void set_dst_addr(sa_family_t family,
164 				struct net_pkt *pkt,
165 				struct net_ipv6_hdr *ipv6_hdr,
166 				struct net_udp_hdr *udp_hdr,
167 				struct sockaddr *dst_addr)
168 {
169 	net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
170 			&ipv6_hdr->src);
171 	net_sin6(dst_addr)->sin6_family = AF_INET6;
172 	net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
173 }
174 
udp_received(struct net_context * context,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,int status,void * user_data)175 static void udp_received(struct net_context *context,
176 			 struct net_pkt *pkt,
177 			 union net_ip_header *ip_hdr,
178 			 union net_proto_header *proto_hdr,
179 			 int status,
180 			 void *user_data)
181 {
182 	struct sockaddr dst_addr;
183 	sa_family_t family = net_pkt_family(pkt);
184 	static char dbg[MAX_DBG_PRINT + 1];
185 	int ret;
186 
187 	snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c",
188 		 family == AF_INET6 ? '6' : '4');
189 
190 	set_dst_addr(family, pkt, ip_hdr->ipv6, proto_hdr->udp, &dst_addr);
191 
192 	ret = build_reply(dbg, pkt, buf_tx);
193 	if (ret < 0) {
194 		LOG_ERR("Cannot send data to peer (%d)", ret);
195 		return;
196 	}
197 
198 	net_pkt_unref(pkt);
199 
200 	ret = net_context_sendto(context, buf_tx, ret, &dst_addr,
201 				 family == AF_INET6 ?
202 				 sizeof(struct sockaddr_in6) :
203 				 sizeof(struct sockaddr_in),
204 				 pkt_sent, K_NO_WAIT, user_data);
205 	if (ret < 0) {
206 		LOG_ERR("Cannot send data to peer (%d)", ret);
207 	}
208 }
209 
setup_udp_recv(struct net_context * udp_recv6)210 static void setup_udp_recv(struct net_context *udp_recv6)
211 {
212 	int ret;
213 
214 	ret = net_context_recv(udp_recv6, udp_received, K_NO_WAIT, NULL);
215 	if (ret < 0) {
216 		LOG_ERR("Cannot receive IPv6 UDP packets");
217 	}
218 }
219 
tcp_received(struct net_context * context,struct net_pkt * pkt,union net_ip_header * ip_hdr,union net_proto_header * proto_hdr,int status,void * user_data)220 static void tcp_received(struct net_context *context,
221 			 struct net_pkt *pkt,
222 			 union net_ip_header *ip_hdr,
223 			 union net_proto_header *proto_hdr,
224 			 int status,
225 			 void *user_data)
226 {
227 	static char dbg[MAX_DBG_PRINT + 1];
228 	sa_family_t family;
229 	int ret;
230 
231 	if (!pkt) {
232 		/* EOF condition */
233 		return;
234 	}
235 
236 	family = net_pkt_family(pkt);
237 
238 	snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c",
239 		 family == AF_INET6 ? '6' : '4');
240 
241 	ret = build_reply(dbg, pkt, buf_tx);
242 	if (ret < 0) {
243 		LOG_ERR("Cannot send data to peer (%d)", ret);
244 		return;
245 	}
246 
247 	net_pkt_unref(pkt);
248 
249 	ret = net_context_send(context, buf_tx, ret, pkt_sent,
250 			       K_NO_WAIT, NULL);
251 	if (ret < 0) {
252 		LOG_ERR("Cannot send data to peer (%d)", ret);
253 		quit();
254 	}
255 }
256 
tcp_accepted(struct net_context * context,struct sockaddr * addr,socklen_t addrlen,int error,void * user_data)257 static void tcp_accepted(struct net_context *context,
258 			 struct sockaddr *addr,
259 			 socklen_t addrlen,
260 			 int error,
261 			 void *user_data)
262 {
263 	int ret;
264 
265 	NET_DBG("Accept called, context %p error %d", context, error);
266 
267 	net_context_set_accepting(context, false);
268 
269 	ret = net_context_recv(context, tcp_received, K_NO_WAIT, NULL);
270 	if (ret < 0) {
271 		LOG_ERR("Cannot receive TCP packet (family %d)",
272 			net_context_get_family(context));
273 	}
274 }
275 
setup_tcp_accept(struct net_context * tcp_recv6)276 static void setup_tcp_accept(struct net_context *tcp_recv6)
277 {
278 	int ret;
279 
280 	ret = net_context_accept(tcp_recv6, tcp_accepted, K_NO_WAIT, NULL);
281 	if (ret < 0) {
282 		LOG_ERR("Cannot receive IPv6 TCP packets (%d)", ret);
283 	}
284 }
285 
listen(void)286 static void listen(void)
287 {
288 	struct net_context *udp_recv6 = { 0 };
289 	struct net_context *tcp_recv6 = { 0 };
290 
291 	if (!get_context(&udp_recv6, &tcp_recv6)) {
292 		LOG_ERR("Cannot get network contexts");
293 		return;
294 	}
295 
296 	LOG_INF("Starting to wait");
297 
298 	setup_tcp_accept(tcp_recv6);
299 	setup_udp_recv(udp_recv6);
300 
301 	k_sem_take(&quit_lock, K_FOREVER);
302 
303 	LOG_INF("Stopping...");
304 
305 	net_context_put(udp_recv6);
306 	net_context_put(tcp_recv6);
307 }
308 
main(void)309 void main(void)
310 {
311 	init_app();
312 
313 	k_thread_create(&thread_data, thread_stack, STACKSIZE,
314 			(k_thread_entry_t)listen,
315 			NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
316 }
317