source: asp3_tinet_ecnl_arm/trunk/ntshell/echonet/echonet_udp6_task.c@ 400

Last change on this file since 400 was 400, checked in by coas-nagasima, 5 years ago

ファイルヘッダーの更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 21.9 KB
Line 
1/*
2 * TOPPERS PROJECT Home Network Working Group Software
3 *
4 * Copyright (C) 2014-2019 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38/*
39 * ECHONET Lite UDP通信処理タスク
40 */
41#if 0 //def SUPPORT_INET6
42
43#include <kernel.h>
44#include <string.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <t_syslog.h>
48#include <t_stdlib.h>
49#include <sil.h>
50
51#include "syssvc/serial.h"
52#include "syssvc/syslog.h"
53#include "echonet.h"
54
55#include <tinet_config.h>
56#include <tinet_defs.h>
57#include <net/net.h>
58#include <netinet/in.h>
59#include <netinet/in_var.h>
60#include <net/ethernet.h>
61#include <net/if.h>
62#include <net/if_var.h>
63#include <net/if6_var.h>
64#include <netinet/in_itron.h>
65
66#include "echonet_task.h"
67#include "echonet_lcl_task.h"
68#include "echonet_dbg.h"
69
70#ifndef ECHONET_UDP_TASK_GET_TIMER
71#define ECHONET_UDP_TASK_GET_TIMER TMO_FEVR
72#endif /* ECHONET_UDP_TASK_GET_TIMER */
73
74#ifndef ECHONET_UDP_TASK_PROGRESS
75#define ECHONET_UDP_TASK_PROGRESS(timer)
76#endif /* ECHONET_UDP_TASK_PROGRESS */
77
78#ifndef ECHONET_UDP_TASK_TIMEOUT
79#define ECHONET_UDP_TASK_TIMEOUT
80#endif /* ECHONET_UDP_TASK_TIMEOUT */
81
82#ifndef ECHONET_UDP_SEND_TO_MBX
83#define ECHONET_UDP_SEND_TO_MBX
84#endif /* ECHONET_UDP_SEND_TO_MBX */
85
86#ifndef ECHONET_NODE_MATCH
87#define ECHONET_NODE_MATCH(enodcb, edata, ipaddr, portno) is_match(enodcb, edata, ipaddr, portno)
88#endif /* ECHONET_NODE_MATCH */
89
90#define IPV6_ADDR_LOCAL_LOOPBACK_INIT \
91 {{{ UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
92 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
93 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), \
94 UINT_C(0x00), UINT_C(0x00), UINT_C(0x00), UINT_C(0x01) }}}
95
96static ECN_ENOD_ID udp_get_id(T_EDATA *edata, const T_IN6_ADDR ipaddr, uint16_t portno);
97static int udp_get_ip(T_IPV6EP *fp_ipep, ECN_ENOD_ID fa_enodid);
98void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len);
99void _ecn_esv_msg(ECN_FBS_ID fbs_id);
100
101/*
102 * 受信したUDPデータをMAILBOXに送る
103 */
104ER _ecn_udp2dtq(const uint8_t *buffer, size_t fa_len, const T_IPV6EP *dst);
105ER _ecn_udp2dtq(const uint8_t *buffer, size_t fa_len, const T_IPV6EP *dst)
106{
107 ECN_FBS_ID a_fbs_id = { 0 };
108 ER a_ret = E_OK;
109 ECN_ENOD_ID a_enod_id;
110 union
111 {
112 const uint8_t *buffer;
113 const T_ECN_EDT_HDR *t_esv;
114 } a_rcv_pkt;
115
116 a_rcv_pkt.buffer = buffer;
117 if ( a_rcv_pkt.t_esv->ecn_hdr.ehd1 != ECN_EDH1_ECHONET_LITE /* ECHONET Lite規格 */
118 || a_rcv_pkt.t_esv->ecn_hdr.ehd2 != ECN_EDH2_FORMAT_1 /* 電文形式1 */) {
119 ECN_DBG_PUT_2("[UDP ECHO SRV] illegal type (0x%02X,0x%02X)", a_rcv_pkt.t_esv->ecn_hdr.ehd1, a_rcv_pkt.t_esv->ecn_hdr.ehd2);
120 return E_PAR;
121 }
122
123#ifdef ECN_DBG_PUT_ENA
124 _ecn_dbg_bindmp(buffer, fa_len);
125#endif
126
127 a_ret = _ecn_fbs_cre(fa_len, &a_fbs_id);
128 if (a_ret != E_OK) {
129 ECN_DBG_PUT_2("[UDP ECHO SRV] _ecn_fbs_cre() result = %d:%s", a_ret, itron_strerror(a_ret));
130 return a_ret;
131 }
132 a_ret = _ecn_fbs_add_data_ex(a_fbs_id, buffer, fa_len);
133 if (a_ret) {
134 ECN_DBG_PUT_2("[UDP ECHO SRV] _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
135 goto lb_except;
136 }
137 a_fbs_id.ptr->hdr.type = ECN_MSG_ECHONET;
138 a_fbs_id.ptr->hdr.target.id = ENOD_LOCAL_ID;
139 a_fbs_id.ptr->hdr.sender.id = ENOD_NOT_MATCH_ID;
140
141 /* IPアドレスからリモートECHONETノードへ変換 */
142 a_enod_id = udp_get_id((T_EDATA *)a_fbs_id.ptr, dst->ipaddr, dst->portno);
143 if (a_enod_id < 0 || tnum_enodadr <= a_enod_id) {
144 ECN_DBG_PUT_1("[UDP ECHO SRV] udp src(%s) echonet-node not found.",
145 ipv62str(NULL, &dst->ipaddr));
146 } else {
147 /* 送信元ECHONETノードを記録 */
148 a_fbs_id.ptr->hdr.sender.id = a_enod_id;
149 }
150 a_fbs_id.ptr->hdr.reply.id = a_fbs_id.ptr->hdr.sender.id;
151
152 /* echonet_taskに送る */
153 a_ret = snd_dtq(ecn_svc_dataqueueid, (intptr_t)a_fbs_id.ptr);
154 if (a_ret != E_OK) {
155 ECN_DBG_PUT_2("[UDP ECHO SRV] snd_dtq(ecn_svc_dataqueueid) result = %d:%s", a_ret, itron_strerror(a_ret));
156 goto lb_except;
157 }
158 return a_ret;
159lb_except:
160 _ecn_fbs_del(a_fbs_id);
161 return a_ret;
162}
163
164/*
165 * ECHONET UDP通信処理タスク
166 */
167void echonet_udp_task(intptr_t exinf)
168{
169 T_IN6_ADDR a_src;
170 ER a_ret, a_ret2;
171 ID tskid;
172 ECN_FBS_SSIZE_T a_snd_len;
173 union
174 {
175 T_MSG *p_msg;
176 ECN_FBS_ID fbs_id;
177 } a_mdt;
178 SYSTIM a_prev, a_now;
179 int a_timer;
180
181 get_tid(&tskid);
182 memcpy(&a_src, in6_get_ifaddr(0), sizeof(T_IN6_ADDR));
183 ECN_DBG_PUT_4("[UDP TSK:%d,%d] started, IP Address: %s ether_max_len: %u",
184 tskid, exinf,
185 ipv62str(NULL, &a_src),
186 ETHER_MAX_LEN);
187 memcpy(enodadrb_table[ENOD_LOCAL_ID].ipaddr, &a_src, sizeof(T_IN6_ADDR));
188
189 syscall(act_tsk(ecn_svc_taskid));
190
191 a_ret = get_tim(&a_now);
192 if (a_ret != E_OK) {
193 ECN_DBG_PUT_2("get_tim() result = %d:%s", a_ret, itron_strerror(a_ret));
194 return;
195 }
196
197 /* メッセージループ */
198 for (;;) {
199 a_prev = a_now;
200
201 a_timer = ECHONET_UDP_TASK_GET_TIMER;
202
203 a_ret = trcv_dtq(ecn_udp_dataqueueid, (intptr_t *)&a_mdt.p_msg, a_timer);
204 if ((a_ret != E_OK) && (a_ret != E_TMOUT)) {
205 ECN_DBG_PUT_2("trcv_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
206 break;
207 }
208
209 a_ret2 = get_tim(&a_now);
210 if (a_ret2 != E_OK) {
211 ECN_DBG_PUT_2("get_tim() result = %d:%s", a_ret2, itron_strerror(a_ret2));
212 break;
213 }
214
215 a_timer = a_now - a_prev;
216 ECHONET_UDP_TASK_PROGRESS(a_timer);
217
218 if (a_ret == E_OK) {
219 /* 送信データ長を取得 */
220 a_snd_len = _ecn_fbs_get_datalen(a_mdt.fbs_id);
221
222 ECN_DBG_PUT_1("[UDP TSK] trcv_dtq() dtq recv (%d byte)", _ecn_fbs_get_datalen(a_mdt.fbs_id));
223
224 if (0 < a_snd_len) {
225 switch(a_mdt.fbs_id.ptr->hdr.type){
226 case ECN_MSG_INTERNAL:
227 _ecn_int_msg(a_mdt.fbs_id, a_snd_len);
228 break;
229 case ECN_MSG_ECHONET:
230 _ecn_esv_msg(a_mdt.fbs_id);
231 break;
232 }
233 }
234
235 _ecn_fbs_del(a_mdt.fbs_id);
236 }
237
238 ECHONET_UDP_TASK_TIMEOUT;
239 }
240}
241
242/* 応答電文用fbs設定(sender/targetの設定) */
243static ER _ecn_udp_cre_req_fbs(ID sender, uint8_t cmd, ECN_FBS_ID *pk_req)
244{
245 ER ret;
246 ECN_FBS_ID req;
247
248 ret = _ecn_fbs_cre(1, &req);
249 if (ret != E_OK) {
250 ECN_DBG_PUT_2("_ecn_udp_cre_req_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
251 return ret;
252 }
253
254 ret = _ecn_fbs_add_data(req, &cmd, sizeof(cmd));
255 if (ret != E_OK) {
256 _ecn_fbs_del(req);
257 ECN_DBG_PUT_2("_ecn_udp_cre_req_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
258 return ret;
259 }
260
261 req.ptr->hdr.type = ECN_MSG_INTERNAL;
262 req.ptr->hdr.sender.dtqid = sender;
263 req.ptr->hdr.target.dtqid = ecn_udp_dataqueueid;
264 req.ptr->hdr.reply.dtqid = sender;
265
266 *pk_req = req;
267
268 return E_OK;
269}
270
271/* 応答電文用fbs設定(sender/targetの設定) */
272static ER _ecn_udp_cre_res_fbs(ECN_FBS_ID req, uint8_t cmd, ECN_FBS_ID *pk_res)
273{
274 ER ret;
275 ECN_FBS_ID res;
276
277 ret = _ecn_fbs_cre(1, &res);
278 if (ret != E_OK) {
279 ECN_DBG_PUT_2("_ecn_udp_cre_res_fbs() : _ecn_fbs_cre() result = %d:%s", ret, itron_strerror(ret));
280 return ret;
281 }
282
283 ret = _ecn_fbs_add_data(res, &cmd, sizeof(cmd));
284 if (ret != E_OK) {
285 _ecn_fbs_del(res);
286 ECN_DBG_PUT_2("_ecn_udp_cre_res_fbs() : _ecn_fbs_add_data() result = %d:%s", ret, itron_strerror(ret));
287 return ret;
288 }
289
290 res.ptr->hdr.type = ECN_MSG_INTERNAL;
291 res.ptr->hdr.sender.dtqid = ecn_udp_dataqueueid;
292 res.ptr->hdr.target.dtqid = req.ptr->hdr.reply.dtqid;
293 res.ptr->hdr.reply.dtqid = ecn_udp_dataqueueid;
294
295 *pk_res = res;
296
297 return E_OK;
298}
299
300/*
301 * 内部メッセージ受信処理
302 */
303void _ecn_int_msg(ECN_FBS_ID fbs_id, ECN_FBS_SSIZE_T a_snd_len)
304{
305 ER result = E_OK, a_ret;
306 ecn_udp_msg_get_ipaddr_req_t msg;
307 ecn_udp_msg_get_ipaddr_error_t err;
308 ECN_FBS_SSIZE_T len;
309 ECN_FBS_ID buf;
310 uint8_t cmd;
311
312 a_ret = _ecn_fbs_get_data(fbs_id, &cmd, 1, &len);
313 if (a_ret != E_OK) {
314 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
315 return;
316 }
317
318 switch(cmd){
319 // IPアドレスを返信
320 case ECN_UDP_MSG_GET_IPADDR_REQ:
321 if (a_snd_len < sizeof(msg)) {
322 result = E_PAR;
323 break;
324 }
325
326 a_snd_len = 0;
327 a_ret = _ecn_fbs_get_data(fbs_id, &msg, sizeof(msg), &a_snd_len);
328 if (a_ret != E_OK) {
329 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
330 }
331
332 if ((msg.enodid < 0) && (msg.enodid >= tnum_enodadr)) {
333 result = E_PAR;
334 break;
335 }
336
337 a_ret = _ecn_udp_cre_res_fbs(fbs_id, ECN_UDP_MSG_GET_IPADDR_RES, &buf);
338 if (a_ret != E_OK) {
339 return;
340 }
341
342 a_ret = _ecn_fbs_add_data_ex(buf, &msg.requestid, offsetof(ecn_udp_msg_get_ipaddr_res_t, enodadrb));
343 if (a_ret != E_OK) {
344 _ecn_fbs_del(buf);
345 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
346 return;
347 }
348
349 a_ret = _ecn_fbs_add_data_ex(buf, &enodadrb_table[msg.enodid], sizeof(enodadrb_table[msg.enodid]));
350 if (a_ret != E_OK) {
351 _ecn_fbs_del(buf);
352 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
353 return;
354 }
355
356 a_ret = psnd_dtq(buf.ptr->hdr.target.dtqid, (intptr_t)buf.ptr);
357 if (a_ret != E_OK) {
358 _ecn_fbs_del(buf);
359 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
360 return;
361 }
362 return;
363 }
364
365 a_ret = _ecn_udp_cre_res_fbs(fbs_id, ECN_UDP_MSG_GET_IPADDR_ERROR, &buf);
366 if (a_ret != E_OK) {
367 return;
368 }
369
370 err.requestid = msg.requestid;
371 err.error = result;
372 a_ret = _ecn_fbs_add_data_ex(buf, &err, sizeof(err));
373 if (a_ret != E_OK) {
374 _ecn_fbs_del(buf);
375 ECN_DBG_PUT_2("_ecn_int_msg() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
376 return;
377 }
378
379 a_ret = psnd_dtq(buf.ptr->hdr.target.dtqid, (intptr_t)buf.ptr);
380 if (a_ret != E_OK) {
381 _ecn_fbs_del(buf);
382 ECN_DBG_PUT_2("_ecn_int_msg() : psnd_dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
383 return;
384 }
385}
386
387/*
388 * ECHONET 電文受信処理
389 */
390void _ecn_esv_msg(ECN_FBS_ID fbs_id)
391{
392 const static T_IN6_ADDR locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
393 /* UDP出力領域(暫定) */
394 static uint_t buffer[(ETHER_MAX_LEN) / sizeof(uint_t) + 1];
395 T_IPV6EP a_dst;
396 ER a_ret;
397 ECN_FBS_SSIZE_T a_snd_len;
398
399 memset(&a_dst.ipaddr, 0, sizeof(a_dst.ipaddr));
400 a_dst.portno = 0;
401 /* 送信先IPアドレス */
402 a_ret = udp_get_ip(&a_dst, fbs_id.ptr->hdr.target.id);
403 if (!a_ret) {
404 ECN_DBG_PUT_4("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X → udp dest(%s)",
405 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
406 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
407 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3,
408 ipv62str(NULL, &a_dst.ipaddr));
409
410 /* fbsから出力領域にデータを抽出 */
411 a_snd_len = 0;
412 a_ret = _ecn_fbs_get_data(fbs_id, buffer, sizeof(buffer), &a_snd_len);
413 if (a_ret != E_OK) {
414 ECN_DBG_PUT_2("[UDP TSK] _ecn_fbs_get_data() result = %d:%s", a_ret, itron_strerror(a_ret));
415 }
416 else if (memcmp(&a_dst.ipaddr, &locl, sizeof(a_dst.ipaddr)) == 0) {
417 /* 送信先が127.0.0.1 → dtqに転送 */
418 ECN_DBG_PUT_1("redirect ecn_udp_dataqueueid → ecn_svc_dataqueueid (esv:0x%02X)",
419 ((T_EDATA *)fbs_id.ptr)->hdr.edata.esv);
420
421 a_ret = _ecn_udp2dtq((const uint8_t *)buffer, a_snd_len, &a_dst);
422 if (a_ret != E_OK) {
423 syslog(LOG_WARNING, "_ecn_esv_msg() : _ecn_udp2dtq() result = %d:%s", a_ret, itron_strerror(a_ret));
424 }
425 }
426 else {
427 ECN_DBG_PUT_2("[UDP TSK] udp6_snd_dat() to:%s %ubyte(s)",
428 ipv62str(NULL, &a_dst.ipaddr), a_snd_len);
429#ifdef ECN_DBG_PUT_ENA
430 _ecn_dbg_bindmp((const uint8_t *)buffer, a_snd_len);
431#endif
432 /* UDP送信 */
433 a_ret = udp6_snd_dat(ecn_udp_cepid, &a_dst, buffer, a_snd_len, TMO_FEVR);
434 if (a_ret < 0) {
435 ECN_DBG_PUT_1("[UDP TSK] send, error: %s", itron_strerror(a_ret));
436 }
437 }
438
439 /* データが長すぎて1パケットに収まらなかった場合 */
440 if (_ecn_fbs_exist_data(fbs_id)) {
441 ECN_DBG_PUT_1("[UDP TSK] send, data so long: %dbyte(s)", _ecn_fbs_get_datalen(fbs_id));
442 }
443 } else {
444 ECN_DBG_PUT_3("[UDP TSK] echonet-node 0x%02X-0x%02X-0x%02X not found.",
445 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx1,
446 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx2,
447 ((T_EDATA *)fbs_id.ptr)->hdr.edata.deoj.eojx3);
448 }
449}
450
451/*
452 * ノンブロッキングコールのコールバック関数
453 */
454ER callback_nblk_udp(ID cepid, FN fncd, void *p_parblk)
455{
456 ER error = E_OK;
457
458 static uint8_t buffer[(ETHER_MAX_LEN) / sizeof(uint_t) + 1];
459
460 T_IPV6EP dst;
461 int a_len;
462
463 switch (fncd) {
464 case TEV_UDP_RCV_DAT:
465 case TFN_UDP_RCV_DAT:
466 /* ECN_CAP_PUT("[UDP ECHO SRV] callback_nblk_udp() recv: %u", *(int *)p_parblk); */
467 memset(buffer, 0, sizeof(buffer));
468 if ((a_len = udp6_rcv_dat(cepid, &dst, buffer, sizeof(buffer) - 1, 20 * 1000)) < 0) {
469 syslog(LOG_WARNING, "[UDP ECHO SRV] recv, error: %s", itron_strerror(a_len));
470 return a_len;
471 }
472#ifdef _MSC_VER
473 /* (開発用) ECHONET用パケット以外は読み捨てる */
474 if (buffer[0] != 0x10 || buffer[1] != 0x81) {
475 return E_OK;
476 }
477#endif
478 ECN_CAP_PUT_4("[UDP ECHO SRV] recv, addr: %s:%d, len: %d, msg: '%s'",
479 ipv62str(NULL, &dst.ipaddr), dst.portno, a_len, buffer);
480 if ((int)sizeof(buffer) <= a_len)
481 a_len = (int)sizeof(buffer) - 1;
482 if (0 < a_len) {
483 ECHONET_UDP_SEND_TO_MBX;
484
485 _ecn_udp2dtq(buffer, a_len, &dst);
486 }
487
488 return E_OK;
489
490 case TFN_UDP_CRE_CEP:
491 case TFN_UDP_SND_DAT:
492 break;
493 default:
494 ECN_CAP_PUT_2("[UDP ECHO SRV] fncd:0x%04X(%s)", -fncd,
495 (fncd == TEV_UDP_RCV_DAT ? "TEV_UDP_RCV_DAT" :
496 (fncd == TFN_UDP_CRE_CEP ? "TFN_UDP_CRE_CEP" :
497 (fncd == TFN_UDP_RCV_DAT ? "TFN_UDP_RCV_DAT" :
498 (fncd == TFN_UDP_SND_DAT ? "TFN_UDP_SND_DAT" : "undef")))));
499
500 error = E_PAR;
501 break;
502 }
503 return error;
504}
505
506/*
507 * リモートECHONETノードの適合確認
508 */
509bool_t is_match(const EOBJCB *enodcb, T_EDATA *edata, const void *_ipaddr, uint16_t portno)
510{
511 /*T_IN6_ADDR *ipaddr = (T_IN6_ADDR *)_ipaddr;*/
512 ER ret;
513 T_ENUM_EPC enm;
514 uint8_t epc;
515 uint8_t pdc;
516 uint8_t p_edt[256];
517 int i, j, k;
518 int count;
519 const EOBJINIB *p_eobj;
520 bool_t match;
521
522 if (!edata)
523 return false;
524
525 /* ノードスタート時インスタンスリスト通知以外は除外 */
526 if ( edata->hdr.edata.esv != ESV_INF
527 || edata->hdr.edata.deoj.eojx1 != EOJ_X1_PROFILE
528 || edata->hdr.edata.deoj.eojx2 != EOJ_X2_NODE_PROFILE
529 || edata->hdr.edata.deoj.eojx3 != 0x01
530 || edata->hdr.edata.seoj.eojx1 != EOJ_X1_PROFILE
531 || edata->hdr.edata.seoj.eojx2 != EOJ_X2_NODE_PROFILE
532 || ( edata->hdr.edata.seoj.eojx3 != 0x01
533 && edata->hdr.edata.seoj.eojx3 != 0x02)) {
534 return false;
535 }
536
537 ret = ecn_itr_ini(&enm, edata);
538 if (ret) {
539 syslog(LOG_WARNING, "is_match(): ecn_itr_ini() result = %d:%s", ret, itron_strerror(ret));
540 return false;
541 }
542 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
543 if (enm.is_eof) {
544 break;
545 }
546 ECN_DBG_PUT_2("is_match(): ecn_itr_nxt() result: epc=0x%02X, pdc=%d", epc, pdc);
547 /* インスタンスリスト通知または自ノードインスタンスリストS以外は除外 */
548 if ((epc != 0xD5) && (epc != 0xD6)) {
549 continue;
550 }
551
552 /* 2バイト目以降にeojが列挙されている */
553 count = (pdc - 1) / sizeof(T_ECN_EOJ);
554
555 /* ノード内の機器オブジェクトを検索 */
556 for (k = 0; k < enodcb->eobjcnt; k++) {
557 p_eobj = enodcb->eobjs[k];
558
559 /* インスタンスリストを確認 */
560 match = false;
561 for (i = 0, j = 1; i < count; i++, j += sizeof(T_ECN_EOJ)) {
562 if (p_eobj->eojx1 != p_edt[j])
563 continue;
564 if (p_eobj->eojx2 != p_edt[j + 1])
565 continue;
566 if (p_eobj->eojx3 != p_edt[j + 2])
567 continue;
568
569 match = true;
570 break;
571 }
572
573 if (!match)
574 return false;
575 }
576
577 /* すべて揃っていたら適合(インスタンスリストの方が多くてもいいこととする) */
578 return true;
579 }
580
581 return false;
582}
583
584/*
585 * IPアドレスからリモートECHONETノードへ変換
586 */
587ECN_ENOD_ID udp_get_id(T_EDATA *edata, const T_IN6_ADDR ipaddr, uint16_t portno)
588{
589 T_ENOD_ADDR *ea;
590 const static T_IN6_ADDR mcst = IPV6_ADDR_LINKLOCAL_ALLNODES_INIT,
591 locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
592 int i;
593
594 if (IN6_ARE_ADDR_EQUAL(&ipaddr, &locl))
595 return ENOD_LOCAL_ID;
596 if (IN6_ARE_ADDR_EQUAL(&ipaddr, in6_get_ifaddr(0)))
597 return ENOD_LOCAL_ID;
598 if (IN6_ARE_ADDR_EQUAL(&ipaddr, &mcst))
599 return ENOD_MULTICAST_ID;
600
601 /* IPアドレスの同じものを検索 */
602 for (i = 0, ea = enodadrb_table; i < tnum_enodadr; i++, ea++) {
603 if (!ea->inuse)
604 continue;
605 if (!IN6_ARE_ADDR_EQUAL(&ea->ipaddr, &ipaddr))
606 continue;
607
608 ECN_CAP_PUT_2("udp_get_id(): ip-found remote(%d) = %s",
609 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
610 return (ECN_ENOD_ID)i;
611 }
612
613 /* 対応するリモートノードを検索 */
614 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
615 if (!ea->inuse)
616 continue;
617 if ((i - ENOD_REMOTE_ID + 1) >= tnum_enodid)
618 break;
619 if ((((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[0] != 0)
620 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[1] != 0)
621 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[2] != 0)
622 || (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[3] != 0))
623 continue;
624 if (!ECHONET_NODE_MATCH(&eobjcb_table[i - ENOD_REMOTE_ID + 1], edata, &ipaddr, portno))
625 continue;
626
627 /* 対応するリモートノードがあればIPアドレスを設定 */
628 memcpy(&ea->ipaddr, &ipaddr, sizeof(T_IN6_ADDR));
629
630 ECN_CAP_PUT_2("udp_get_id(): enod-found remote(%d) = %s",
631 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
632 return (ECN_ENOD_ID)i;
633 }
634
635 /* 空き領域を探して自動登録 */
636 for (i = ENOD_REMOTE_ID, ea = &enodadrb_table[ENOD_REMOTE_ID]; i < tnum_enodadr; i++, ea++) {
637 if (ea->inuse)
638 continue;
639
640 ea->inuse = true;
641 memcpy(&ea->ipaddr, &ipaddr, sizeof(T_IN6_ADDR));
642
643 ECN_CAP_PUT_2("udp_get_id(): empty-found remote(%d) = %s",
644 i - ENOD_REMOTE_ID, ipv62str(NULL, &ipaddr));
645 return (ECN_ENOD_ID)i;
646 }
647
648 return ENOD_NOT_MATCH_ID;
649}
650
651/*
652 * リモートECHONETノードからIPアドレスへ変換
653 */
654int udp_get_ip(T_IPV6EP *fp_ipep, ECN_ENOD_ID fa_enodid)
655{
656 T_ENOD_ADDR *ea;
657 const static T_IN6_ADDR mcst = IPV6_ADDR_LINKLOCAL_ALLNODES_INIT,
658 locl = IPV6_ADDR_LOCAL_LOOPBACK_INIT;
659
660 if (!fp_ipep)
661 return -1; /* NG */
662
663 fp_ipep->portno = 3610;
664
665 if (fa_enodid == ENOD_MULTICAST_ID) {
666 /* targetがENOD_MULTICAST_IDの場合、マルチキャストを行う */
667 memcpy(&fp_ipep->ipaddr, &mcst, sizeof(T_IN6_ADDR));
668 return 0; /* ok */
669 }
670
671 if (fa_enodid < ENOD_REMOTE_ID) {
672 /* targetが未定義・LOCAL・APIの場合、ローカル配送を行う */
673 memcpy(&fp_ipep->ipaddr, &locl, sizeof(T_IN6_ADDR));
674 return 0; /* ok */
675 }
676
677 if (fa_enodid >= tnum_enodadr)
678 return -1; /* NG */
679
680 ea = &enodadrb_table[fa_enodid];
681 if (!ea->inuse)
682 return -1; /* NG */
683
684 if ((((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[0] == 0)
685 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[1] == 0)
686 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[2] == 0)
687 && (((T_IN6_ADDR *)ea->ipaddr)->__u6_addr.__u6_addr32[3] == 0))
688 return -1; /* NG */
689
690 memcpy(&fp_ipep->ipaddr, &ea->ipaddr, sizeof(T_IN6_ADDR));
691 return 0; /* ok */
692}
693
694ER ecn_udp_get_ipaddr(ID sender, int requestid, ECN_ENOD_ID enodid, ECN_FBS_ID *pk_req)
695{
696 ER a_ret;
697 ECN_FBS_ID req;
698
699 a_ret = _ecn_udp_cre_req_fbs(sender, ECN_UDP_MSG_GET_IPADDR_REQ, &req);
700 if (a_ret != E_OK) {
701 return a_ret;
702 }
703
704 a_ret = _ecn_fbs_add_data_ex(req, &requestid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->requestid));
705 if (a_ret != E_OK) {
706 _ecn_fbs_del(req);
707 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
708 return a_ret;
709 }
710
711 a_ret = _ecn_fbs_add_data_ex(req, &enodid, sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodid));
712 if (a_ret != E_OK) {
713 _ecn_fbs_del(req);
714 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
715 return a_ret;
716 }
717
718 a_ret = _ecn_fbs_add_data_ex(req, &enodadrb_table[enodid], sizeof(((ecn_udp_msg_get_ipaddr_res_t *)0)->enodadrb));
719 if (a_ret != E_OK) {
720 _ecn_fbs_del(req);
721 ECN_DBG_PUT_2("ecn_udp_get_ipaddr() : _ecn_fbs_add_data_ex() result = %d:%s", a_ret, itron_strerror(a_ret));
722 return a_ret;
723 }
724
725 *pk_req = req;
726
727 return E_OK;
728}
729
730char *ipaddr2str(char *buf, int bubsz, uint8_t *ipaddr)
731{
732 return ipv62str(buf, (T_IN6_ADDR *)ipaddr);
733}
734
735#endif
Note: See TracBrowser for help on using the repository browser.