source: mainline/uspace/srv/net/inetsrv/inetcfg.c@ 02a09ed

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 02a09ed was 02a09ed, checked in by Martin Decky <martin@…>, 12 years ago

add basic infrastructure for IPv6 (inactive)
make inet_addr_t a universal address type

  • Property mode set to 100644
File size: 16.2 KB
Line 
1/*
2 * Copyright (c) 2012 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup inet
30 * @{
31 */
32/**
33 * @file
34 * @brief
35 */
36
37#include <async.h>
38#include <errno.h>
39#include <macros.h>
40#include <io/log.h>
41#include <ipc/inet.h>
42#include <loc.h>
43#include <stdlib.h>
44#include <str.h>
45#include <sys/types.h>
46
47#include "addrobj.h"
48#include "inetsrv.h"
49#include "inet_link.h"
50#include "inetcfg.h"
51#include "sroute.h"
52
53static int inetcfg_addr_create_static(char *name, inet_naddr_t *naddr,
54 sysarg_t link_id, sysarg_t *addr_id)
55{
56 inet_link_t *ilink;
57 inet_addrobj_t *addr;
58 inet_addr_t iaddr;
59 int rc;
60
61 ilink = inet_link_get_by_id(link_id);
62 if (ilink == NULL) {
63 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %lu not found.",
64 (unsigned long) link_id);
65 return ENOENT;
66 }
67
68 addr = inet_addrobj_new();
69 if (addr == NULL) {
70 *addr_id = 0;
71 return ENOMEM;
72 }
73
74 addr->naddr = *naddr;
75 addr->ilink = ilink;
76 addr->name = str_dup(name);
77 rc = inet_addrobj_add(addr);
78 if (rc != EOK) {
79 log_msg(LOG_DEFAULT, LVL_DEBUG, "Duplicate address name '%s'.", addr->name);
80 inet_addrobj_delete(addr);
81 return rc;
82 }
83
84 inet_naddr_addr(&addr->naddr, &iaddr);
85 rc = iplink_addr_add(ilink->iplink, &iaddr);
86 if (rc != EOK) {
87 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed setting IP address on internet link.");
88 inet_addrobj_remove(addr);
89 inet_addrobj_delete(addr);
90 return rc;
91 }
92
93 return EOK;
94}
95
96static int inetcfg_addr_delete(sysarg_t addr_id)
97{
98 inet_addrobj_t *addr;
99
100 addr = inet_addrobj_get_by_id(addr_id);
101 if (addr == NULL)
102 return ENOENT;
103
104 inet_addrobj_remove(addr);
105 inet_addrobj_delete(addr);
106
107 return EOK;
108}
109
110static int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
111{
112 inet_addrobj_t *addr;
113
114 addr = inet_addrobj_get_by_id(addr_id);
115 if (addr == NULL)
116 return ENOENT;
117
118 ainfo->naddr = addr->naddr;
119 ainfo->ilink = addr->ilink->svc_id;
120 ainfo->name = str_dup(addr->name);
121
122 return EOK;
123}
124
125static int inetcfg_addr_get_id(char *name, sysarg_t link_id, sysarg_t *addr_id)
126{
127 inet_link_t *ilink;
128 inet_addrobj_t *addr;
129
130 ilink = inet_link_get_by_id(link_id);
131 if (ilink == NULL) {
132 log_msg(LOG_DEFAULT, LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
133 return ENOENT;
134 }
135
136 addr = inet_addrobj_find_by_name(name, ilink);
137 if (addr == NULL) {
138 log_msg(LOG_DEFAULT, LVL_DEBUG, "Address '%s' not found.", name);
139 return ENOENT;
140 }
141
142 *addr_id = addr->id;
143 return EOK;
144}
145
146static int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
147{
148 return inet_addrobj_get_id_list(addrs, count);
149}
150
151static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count)
152{
153 return ENOTSUP;
154}
155
156static int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
157{
158 return inet_sroute_get_id_list(sroutes, count);
159}
160
161static int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
162{
163 inet_link_t *ilink;
164
165 ilink = inet_link_get_by_id(link_id);
166 if (ilink == NULL) {
167 return ENOENT;
168 }
169
170 linfo->name = str_dup(ilink->svc_name);
171 linfo->def_mtu = ilink->def_mtu;
172 return EOK;
173}
174
175static int inetcfg_sroute_create(char *name, inet_naddr_t *dest,
176 inet_addr_t *router, sysarg_t *sroute_id)
177{
178 inet_sroute_t *sroute;
179
180 sroute = inet_sroute_new();
181 if (sroute == NULL) {
182 *sroute_id = 0;
183 return ENOMEM;
184 }
185
186 sroute->dest = *dest;
187 sroute->router = *router;
188 sroute->name = str_dup(name);
189 inet_sroute_add(sroute);
190
191 *sroute_id = sroute->id;
192 return EOK;
193}
194
195static int inetcfg_sroute_delete(sysarg_t sroute_id)
196{
197 inet_sroute_t *sroute;
198
199 sroute = inet_sroute_get_by_id(sroute_id);
200 if (sroute == NULL)
201 return ENOENT;
202
203 inet_sroute_remove(sroute);
204 inet_sroute_delete(sroute);
205
206 return EOK;
207}
208
209static int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
210{
211 inet_sroute_t *sroute;
212
213 sroute = inet_sroute_get_by_id(sroute_id);
214 if (sroute == NULL)
215 return ENOENT;
216
217 srinfo->dest = sroute->dest;
218 srinfo->router = sroute->router;
219 srinfo->name = str_dup(sroute->name);
220
221 return EOK;
222}
223
224static int inetcfg_sroute_get_id(char *name, sysarg_t *sroute_id)
225{
226 inet_sroute_t *sroute;
227
228 sroute = inet_sroute_find_by_name(name);
229 if (sroute == NULL) {
230 log_msg(LOG_DEFAULT, LVL_DEBUG, "Static route '%s' not found.", name);
231 return ENOENT;
232 }
233
234 *sroute_id = sroute->id;
235 return EOK;
236}
237
238static void inetcfg_addr_create_static_srv(ipc_callid_t iid,
239 ipc_call_t *icall)
240{
241 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_create_static_srv()");
242
243 sysarg_t link_id = IPC_GET_ARG1(*icall);
244
245 ipc_callid_t callid;
246 size_t size;
247 if (!async_data_write_receive(&callid, &size)) {
248 async_answer_0(callid, EINVAL);
249 async_answer_0(iid, EINVAL);
250 return;
251 }
252
253 if (size != sizeof(inet_naddr_t)) {
254 async_answer_0(callid, EINVAL);
255 async_answer_0(iid, EINVAL);
256 return;
257 }
258
259 inet_naddr_t naddr;
260 int rc = async_data_write_finalize(callid, &naddr, size);
261 if (rc != EOK) {
262 async_answer_0(callid, rc);
263 async_answer_0(iid, rc);
264 return;
265 }
266
267 char *name;
268 rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
269 0, NULL);
270 if (rc != EOK) {
271 async_answer_0(iid, rc);
272 return;
273 }
274
275 sysarg_t addr_id = 0;
276 rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id);
277 free(name);
278 async_answer_1(iid, rc, addr_id);
279}
280
281static void inetcfg_addr_delete_srv(ipc_callid_t callid, ipc_call_t *call)
282{
283 sysarg_t addr_id;
284 int rc;
285
286 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_delete_srv()");
287
288 addr_id = IPC_GET_ARG1(*call);
289
290 rc = inetcfg_addr_delete(addr_id);
291 async_answer_0(callid, rc);
292}
293
294static void inetcfg_addr_get_srv(ipc_callid_t iid, ipc_call_t *icall)
295{
296 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_get_srv()");
297
298 sysarg_t addr_id = IPC_GET_ARG1(*icall);
299
300 inet_addr_info_t ainfo;
301
302 inet_naddr_any(&ainfo.naddr);
303 ainfo.ilink = 0;
304 ainfo.name = NULL;
305
306 int rc = inetcfg_addr_get(addr_id, &ainfo);
307 if (rc != EOK) {
308 async_answer_0(iid, rc);
309 return;
310 }
311
312 ipc_callid_t callid;
313 size_t size;
314 if (!async_data_read_receive(&callid, &size)) {
315 async_answer_0(callid, EREFUSED);
316 async_answer_0(iid, EREFUSED);
317 return;
318 }
319
320 if (size != sizeof(inet_naddr_t)) {
321 async_answer_0(callid, EINVAL);
322 async_answer_0(iid, EINVAL);
323 return;
324 }
325
326 rc = async_data_read_finalize(callid, &ainfo.naddr, size);
327 if (rc != EOK) {
328 async_answer_0(callid, rc);
329 async_answer_0(iid, rc);
330 return;
331 }
332
333 if (!async_data_read_receive(&callid, &size)) {
334 async_answer_0(callid, EREFUSED);
335 async_answer_0(iid, EREFUSED);
336 return;
337 }
338
339 rc = async_data_read_finalize(callid, ainfo.name,
340 min(size, str_size(ainfo.name)));
341 free(ainfo.name);
342
343 if (rc != EOK) {
344 async_answer_0(callid, rc);
345 async_answer_0(iid, rc);
346 return;
347 }
348
349 async_answer_1(iid, (sysarg_t) rc, ainfo.ilink);
350}
351
352static void inetcfg_addr_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
353{
354 char *name;
355 sysarg_t link_id;
356 sysarg_t addr_id;
357 int rc;
358
359 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_addr_get_id_srv()");
360
361 link_id = IPC_GET_ARG1(*call);
362
363 rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
364 0, NULL);
365 if (rc != EOK) {
366 async_answer_0(callid, rc);
367 return;
368 }
369
370 addr_id = 0;
371 rc = inetcfg_addr_get_id(name, link_id, &addr_id);
372 free(name);
373 async_answer_1(callid, rc, addr_id);
374}
375
376static void inetcfg_get_addr_list_srv(ipc_callid_t callid, ipc_call_t *call)
377{
378 ipc_callid_t rcallid;
379 size_t count;
380 size_t max_size;
381 size_t act_size;
382 size_t size;
383 sysarg_t *id_buf;
384 int rc;
385
386 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_addr_list_srv()");
387
388 if (!async_data_read_receive(&rcallid, &max_size)) {
389 async_answer_0(rcallid, EREFUSED);
390 async_answer_0(callid, EREFUSED);
391 return;
392 }
393
394 rc = inetcfg_get_addr_list(&id_buf, &count);
395 if (rc != EOK) {
396 async_answer_0(rcallid, rc);
397 async_answer_0(callid, rc);
398 return;
399 }
400
401 act_size = count * sizeof(sysarg_t);
402 size = min(act_size, max_size);
403
404 sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
405 free(id_buf);
406
407 async_answer_1(callid, retval, act_size);
408}
409
410static void inetcfg_get_link_list_srv(ipc_callid_t callid, ipc_call_t *call)
411{
412 ipc_callid_t rcallid;
413 size_t max_size;
414 size_t act_size;
415 size_t size;
416 sysarg_t *id_buf;
417 int rc;
418
419 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_link_list_srv()");
420
421 if (!async_data_read_receive(&rcallid, &max_size)) {
422 async_answer_0(rcallid, EREFUSED);
423 async_answer_0(callid, EREFUSED);
424 return;
425 }
426
427 rc = inetcfg_get_link_list(&id_buf, &act_size);
428 if (rc != EOK) {
429 async_answer_0(rcallid, rc);
430 async_answer_0(callid, rc);
431 return;
432 }
433
434 size = min(act_size, max_size);
435
436 sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
437 free(id_buf);
438
439 async_answer_1(callid, retval, act_size);
440}
441
442static void inetcfg_get_sroute_list_srv(ipc_callid_t callid, ipc_call_t *call)
443{
444 ipc_callid_t rcallid;
445 size_t count;
446 size_t max_size;
447 size_t act_size;
448 size_t size;
449 sysarg_t *id_buf;
450 int rc;
451
452 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
453
454 if (!async_data_read_receive(&rcallid, &max_size)) {
455 async_answer_0(rcallid, EREFUSED);
456 async_answer_0(callid, EREFUSED);
457 return;
458 }
459
460 rc = inetcfg_get_sroute_list(&id_buf, &count);
461 if (rc != EOK) {
462 async_answer_0(rcallid, rc);
463 async_answer_0(callid, rc);
464 return;
465 }
466
467 act_size = count * sizeof(sysarg_t);
468 size = min(act_size, max_size);
469
470 sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
471 free(id_buf);
472
473 async_answer_1(callid, retval, act_size);
474}
475
476static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call)
477{
478 ipc_callid_t rcallid;
479 size_t max_size;
480
481 sysarg_t link_id;
482 inet_link_info_t linfo;
483 int rc;
484
485 link_id = IPC_GET_ARG1(*call);
486 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_link_get_srv()");
487
488 linfo.name = NULL;
489
490 if (!async_data_read_receive(&rcallid, &max_size)) {
491 async_answer_0(rcallid, EREFUSED);
492 async_answer_0(callid, EREFUSED);
493 return;
494 }
495
496 rc = inetcfg_link_get(link_id, &linfo);
497 if (rc != EOK) {
498 async_answer_0(rcallid, rc);
499 async_answer_0(callid, rc);
500 return;
501 }
502
503 sysarg_t retval = async_data_read_finalize(rcallid, linfo.name,
504 min(max_size, str_size(linfo.name)));
505 free(linfo.name);
506
507 async_answer_1(callid, retval, linfo.def_mtu);
508}
509
510static void inetcfg_sroute_create_srv(ipc_callid_t iid,
511 ipc_call_t *icall)
512{
513 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_create_srv()");
514
515 ipc_callid_t callid;
516 size_t size;
517 if (!async_data_write_receive(&callid, &size)) {
518 async_answer_0(callid, EINVAL);
519 async_answer_0(iid, EINVAL);
520 return;
521 }
522
523 if (size != sizeof(inet_naddr_t)) {
524 async_answer_0(callid, EINVAL);
525 async_answer_0(iid, EINVAL);
526 return;
527 }
528
529 inet_naddr_t dest;
530 int rc = async_data_write_finalize(callid, &dest, size);
531 if (rc != EOK) {
532 async_answer_0(callid, rc);
533 async_answer_0(iid, rc);
534 return;
535 }
536
537 if (!async_data_write_receive(&callid, &size)) {
538 async_answer_0(callid, EINVAL);
539 async_answer_0(iid, EINVAL);
540 return;
541 }
542
543 if (size != sizeof(inet_addr_t)) {
544 async_answer_0(callid, EINVAL);
545 async_answer_0(iid, EINVAL);
546 return;
547 }
548
549 inet_addr_t router;
550 rc = async_data_write_finalize(callid, &router, size);
551 if (rc != EOK) {
552 async_answer_0(callid, rc);
553 async_answer_0(iid, rc);
554 return;
555 }
556
557 char *name;
558 rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
559 0, NULL);
560 if (rc != EOK) {
561 async_answer_0(iid, rc);
562 return;
563 }
564
565 sysarg_t sroute_id = 0;
566 rc = inetcfg_sroute_create(name, &dest, &router, &sroute_id);
567 free(name);
568 async_answer_1(iid, rc, sroute_id);
569}
570
571static void inetcfg_sroute_delete_srv(ipc_callid_t callid, ipc_call_t *call)
572{
573 sysarg_t sroute_id;
574 int rc;
575
576 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_delete_srv()");
577
578 sroute_id = IPC_GET_ARG1(*call);
579
580 rc = inetcfg_sroute_delete(sroute_id);
581 async_answer_0(callid, rc);
582}
583
584static void inetcfg_sroute_get_srv(ipc_callid_t iid, ipc_call_t *icall)
585{
586 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_get_srv()");
587
588 sysarg_t sroute_id = IPC_GET_ARG1(*icall);
589
590 inet_sroute_info_t srinfo;
591
592 inet_naddr_any(&srinfo.dest);
593 inet_addr_any(&srinfo.router);
594 srinfo.name = NULL;
595
596 int rc = inetcfg_sroute_get(sroute_id, &srinfo);
597 if (rc != EOK) {
598 async_answer_0(iid, rc);
599 return;
600 }
601
602 ipc_callid_t callid;
603 size_t size;
604 if (!async_data_read_receive(&callid, &size)) {
605 async_answer_0(callid, EREFUSED);
606 async_answer_0(iid, EREFUSED);
607 return;
608 }
609
610 if (size != sizeof(inet_naddr_t)) {
611 async_answer_0(callid, EINVAL);
612 async_answer_0(iid, EINVAL);
613 return;
614 }
615
616 rc = async_data_read_finalize(callid, &srinfo.dest, size);
617 if (rc != EOK) {
618 async_answer_0(callid, rc);
619 async_answer_0(iid, rc);
620 return;
621 }
622
623 if (!async_data_read_receive(&callid, &size)) {
624 async_answer_0(callid, EREFUSED);
625 async_answer_0(iid, EREFUSED);
626 return;
627 }
628
629 if (size != sizeof(inet_addr_t)) {
630 async_answer_0(callid, EINVAL);
631 async_answer_0(iid, EINVAL);
632 return;
633 }
634
635 rc = async_data_read_finalize(callid, &srinfo.router, size);
636 if (rc != EOK) {
637 async_answer_0(callid, rc);
638 async_answer_0(iid, rc);
639 return;
640 }
641
642 if (!async_data_read_receive(&callid, &size)) {
643 async_answer_0(callid, EREFUSED);
644 async_answer_0(iid, EREFUSED);
645 return;
646 }
647
648 rc = async_data_read_finalize(callid, srinfo.name,
649 min(size, str_size(srinfo.name)));
650 free(srinfo.name);
651
652 async_answer_0(iid, (sysarg_t) rc);
653}
654
655static void inetcfg_sroute_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
656{
657 char *name;
658 sysarg_t sroute_id;
659 int rc;
660
661 log_msg(LOG_DEFAULT, LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
662
663 rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
664 0, NULL);
665 if (rc != EOK) {
666 async_answer_0(callid, rc);
667 return;
668 }
669
670 sroute_id = 0;
671 rc = inetcfg_sroute_get_id(name, &sroute_id);
672 free(name);
673 async_answer_1(callid, rc, sroute_id);
674}
675
676void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
677{
678 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_cfg_conn()");
679
680 /* Accept the connection */
681 async_answer_0(iid, EOK);
682
683 while (true) {
684 ipc_call_t call;
685 ipc_callid_t callid = async_get_call(&call);
686 sysarg_t method = IPC_GET_IMETHOD(call);
687
688 if (!method) {
689 /* The other side has hung up */
690 async_answer_0(callid, EOK);
691 return;
692 }
693
694 switch (method) {
695 case INETCFG_ADDR_CREATE_STATIC:
696 inetcfg_addr_create_static_srv(callid, &call);
697 break;
698 case INETCFG_ADDR_DELETE:
699 inetcfg_addr_delete_srv(callid, &call);
700 break;
701 case INETCFG_ADDR_GET:
702 inetcfg_addr_get_srv(callid, &call);
703 break;
704 case INETCFG_ADDR_GET_ID:
705 inetcfg_addr_get_id_srv(callid, &call);
706 break;
707 case INETCFG_GET_ADDR_LIST:
708 inetcfg_get_addr_list_srv(callid, &call);
709 break;
710 case INETCFG_GET_LINK_LIST:
711 inetcfg_get_link_list_srv(callid, &call);
712 break;
713 case INETCFG_GET_SROUTE_LIST:
714 inetcfg_get_sroute_list_srv(callid, &call);
715 break;
716 case INETCFG_LINK_GET:
717 inetcfg_link_get_srv(callid, &call);
718 break;
719 case INETCFG_SROUTE_CREATE:
720 inetcfg_sroute_create_srv(callid, &call);
721 break;
722 case INETCFG_SROUTE_DELETE:
723 inetcfg_sroute_delete_srv(callid, &call);
724 break;
725 case INETCFG_SROUTE_GET:
726 inetcfg_sroute_get_srv(callid, &call);
727 break;
728 case INETCFG_SROUTE_GET_ID:
729 inetcfg_sroute_get_id_srv(callid, &call);
730 break;
731 default:
732 async_answer_0(callid, EINVAL);
733 }
734 }
735}
736
737/** @}
738 */
Note: See TracBrowser for help on using the repository browser.