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