1 /* $Id: Libdnet.xs,v 09f6d620bca4 2012/11/02 16:39:39 gomor $ */
2
3 /*
4 * Copyright (c) 2004 Vlad Manilici
5 * Copyright (c) 2008-2012 Patrice <GomoR> Auffret
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "EXTERN.h"
33 #include "perl.h"
34 #include "XSUB.h"
35
36 #include <stdio.h>
37 #include <dnet.h>
38
39 #ifdef DNET_BLOB_H
40 typedef blob_t Blob;
41 #endif
42
43 #ifdef DNET_ETH_H
44 typedef eth_t EthHandle;
45 typedef eth_addr_t EthAddr;
46 #endif
47
48 #ifdef DNET_INTF_H
49 typedef intf_t IntfHandle;
50 #endif
51
52 #ifdef DNET_ARP_H
53 typedef arp_t ArpHandle;
54 #endif
55
56 #ifdef DNET_FW_H
57 typedef fw_t FwHandle;
58 #endif
59
60 #ifdef DNET_ROUTE_H
61 typedef route_t RouteHandle;
62 #endif
63
64 #ifdef DNET_TUN_H
65 typedef tun_t TunHandle;
66 #endif
67
68 #ifdef DNET_IP_H
69 typedef ip_t IpHandle;
70 #endif
71
72 typedef struct intf_entry IntfEntry;
73 typedef struct arp_entry ArpEntry;
74 typedef struct fw_rule FwRule;
75 typedef struct route_entry RouteEntry;
76
77 #include "c/intf_entry.c"
78 #include "c/arp_entry.c"
79 #include "c/route_entry.c"
80 #include "c/fw_rule.c"
81
82 static SV * keepSub = (SV *)NULL;
83
84 static int
intf_callback(IntfEntry * entry,SV * data)85 intf_callback(IntfEntry *entry, SV *data)
86 {
87 dSP;
88 int ret;
89 SV *e = intf_c2sv(entry);
90 ENTER; SAVETMPS; PUSHMARK(SP);
91 XPUSHs(e);
92 XPUSHs(data);
93 PUTBACK;
94 call_sv(keepSub, G_DISCARD);
95 SPAGAIN;
96 FREETMPS; LEAVE;
97 return 0;
98 }
99
100 static int
route_callback(RouteEntry * entry,SV * data)101 route_callback(RouteEntry *entry, SV *data)
102 {
103 dSP;
104 int ret;
105 SV *e = route_c2sv(entry);
106 ENTER; SAVETMPS; PUSHMARK(SP);
107 XPUSHs(e);
108 XPUSHs(data);
109 //XPUSHs(sv_setref_pv(sv_newmortal(), "RouteEntryPtr", entry));
110 //XPUSHs(sv_setref_pv(sv_newmortal(), Nullch, data));
111 PUTBACK;
112 call_sv(keepSub, G_DISCARD);
113 SPAGAIN;
114 //ret = POPi;
115 FREETMPS; LEAVE;
116 //return ret;
117 return 0;
118 }
119
120 static int
arp_callback(ArpEntry * entry,SV * data)121 arp_callback(ArpEntry *entry, SV *data)
122 {
123 dSP;
124 int ret;
125 SV *e = arp_c2sv(entry);
126 ENTER; SAVETMPS; PUSHMARK(SP);
127 XPUSHs(e);
128 XPUSHs(data);
129 PUTBACK;
130 call_sv(keepSub, G_DISCARD);
131 SPAGAIN;
132 FREETMPS; LEAVE;
133 return 0;
134 }
135
136 static int
fw_callback(FwRule * rule,SV * data)137 fw_callback(FwRule *rule, SV *data)
138 {
139 dSP;
140 int ret;
141 SV *e = fw_c2sv(rule);
142 ENTER; SAVETMPS; PUSHMARK(SP);
143 XPUSHs(e);
144 XPUSHs(data);
145 PUTBACK;
146 call_sv(keepSub, G_DISCARD);
147 SPAGAIN;
148 FREETMPS; LEAVE;
149 return 0;
150 }
151
intf2hash(struct intf_entry * IeInt)152 HV * intf2hash(struct intf_entry *IeInt){
153 HV *HvInt, *HvUndef;
154 SV *SvData, *SvKey;
155 char *StrAddr;
156
157 /* prepare undefined hash */
158 HvUndef = newHV();
159 hv_undef(HvUndef);
160
161 HvInt = newHV();
162
163 /* intf_len */
164 SvKey = newSVpv("len", 0);
165 SvData = newSVnv((double) IeInt->intf_len);
166 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
167 warn("intf2hash: error: intf_len\n");
168 return HvUndef;
169 }
170
171 /* intf_name */
172 SvKey = newSVpv("name", 0);
173 SvData = newSVpv(IeInt->intf_name, 0);
174 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
175 warn("intf2hash: error: int_name\n");
176 return HvUndef;
177 }
178
179 /* intf_type */
180 SvKey = newSVpv("type", 0);
181 SvData = newSVnv((double) IeInt->intf_type);
182 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
183 warn("intf2hash: error: intf_type\n");
184 return HvUndef;
185 }
186
187 /* intf_flags */
188 SvKey = newSVpv("flags", 0);
189 SvData = newSVnv((double) IeInt->intf_flags);
190 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
191 warn("intf2hash: error: intf_flags\n");
192 return HvUndef;
193 }
194
195 /* intf_mtu */
196 SvKey = newSVpv("mtu", 0);
197 SvData = newSVnv((double) IeInt->intf_mtu);
198 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
199 warn("intf2hash: error: intf_mtu\n");
200 return HvUndef;
201 }
202
203 /* intf_addr */
204 SvKey = newSVpv("addr", 0);
205 /* does not allways exist */
206 StrAddr = addr_ntoa(&(IeInt->intf_addr));
207 if( StrAddr == NULL ){
208 SvData = &PL_sv_undef;
209 }else{
210 SvData = newSVpv(addr_ntoa(&(IeInt->intf_addr)), 0);
211 }
212 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
213 warn("intf2hash: error: intf_addr\n");
214 return HvUndef;
215 }
216
217 /* intf_dst_addr */
218 SvKey = newSVpv("dst_addr", 0);
219 /* does not allways exist */
220 StrAddr = addr_ntoa(&(IeInt->intf_dst_addr));
221 if( StrAddr == NULL ){
222 SvData = &PL_sv_undef;
223 }else{
224 SvData = newSVpv(addr_ntoa(&(IeInt->intf_dst_addr)), 0);
225 }
226 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
227 warn("intf2hash: error: intf_dst_addr\n");
228 return HvUndef;
229 }
230
231 /* intf_link_addr */
232 SvKey = newSVpv("link_addr", 0);
233 /* does not allways exist */
234 StrAddr = addr_ntoa(&(IeInt->intf_link_addr));
235 if( StrAddr == NULL ){
236 SvData = &PL_sv_undef;
237 }else{
238 SvData = newSVpv(addr_ntoa(&(IeInt->intf_link_addr)), 0);
239 }
240 if( hv_store_ent(HvInt, SvKey, SvData, 0) == NULL ){
241 warn("intf2hash: error: intf_link_addr\n");
242 return HvUndef;
243 }
244
245 /* XXX skipped the aliases problematic */
246
247 return HvInt;
248 }
249
250 MODULE = Net::Libdnet PACKAGE = Net::Libdnet
251 PROTOTYPES: DISABLE
252
253 #
254 # The following are obsolete functions, but stills there for compatibility reasons
255 #
256
257 SV *
258 _obsolete_addr_cmp(SvA, SvB)
259 SV *SvA;
260 SV *SvB;
261 PROTOTYPE: $$
262 CODE:
263 char *StrA, *StrB;
264 struct addr SadA, SadB;
265 int len;
266
267 /*
268 we cannot avoid ugly nesting, because
269 return and goto are out of scope
270 */
271
272 /* check input */
273 if( !SvOK(SvA) ){
274 warn("addr_cmp: undef input (1)\n");
275 RETVAL = &PL_sv_undef;
276 }else if( !SvOK(SvB) ){
277 warn("addr_cmp: undef input (2)\n");
278 RETVAL = &PL_sv_undef;
279 }else{
280 /* A: SV -> string */
281 StrA = (char *) SvPV(SvA, len);
282 /* A: string -> struct addr */
283 if( addr_aton(StrA, &SadA) < 0 ){
284 warn("addr_cmp: addr_aton: error (1)\n");
285 RETVAL = &PL_sv_undef;
286 }else{
287 /* B: SV -> string */
288 StrB = (char *) SvPV(SvB, len);
289 /* B: string -> struct addr */
290 if( addr_aton(StrB, &SadB) < 0 ){
291 warn("addr_cmp: addr_aton: error (2)\n");
292 RETVAL = &PL_sv_undef;
293 }else{
294 /* compute output */
295 RETVAL = newSVnv((double) addr_cmp(&SadA, &SadB));
296 }
297 }
298 }
299 OUTPUT:
300 RETVAL
301
302 SV *
303 _obsolete_addr_bcast(SvAd)
304 SV *SvAd;
305 PROTOTYPE: $
306 CODE:
307 char *StrAd;
308 struct addr SadAd, SadBc;
309 int len;
310
311 /* check input */
312 if( !SvOK(SvAd) ){
313 warn("addr_bcast: undef input\n");
314 RETVAL = &PL_sv_undef;
315 }else{
316 /* address: SV -> string */
317 StrAd = (char *) SvPV(SvAd, len);
318 /* address: string -> struct addr */
319 if( addr_aton(StrAd, &SadAd) < 0 ){
320 warn("addr_bcast: addr_aton: error\n");
321 RETVAL = &PL_sv_undef;
322 /* compute output */
323 }else if( addr_bcast(&SadAd, &SadBc) < 0 ){
324 warn("addr_bcast: error\n");
325 RETVAL = &PL_sv_undef;
326 }else{
327 /* broadcast: struct addr -> SV */
328 if( (StrAd = addr_ntoa((struct addr *) &SadBc)) == NULL){
329 warn("addr_bcast: addr_ntoa: error\n");
330 RETVAL = &PL_sv_undef;
331 }else{
332 /* 0 means Perl does strlen() itself */
333 RETVAL = newSVpv(StrAd, 0);
334 }
335 }
336 }
337 OUTPUT:
338 RETVAL
339
340 SV *
341 _obsolete_addr_net(SvAd)
342 SV *SvAd;
343 PROTOTYPE: $
344 CODE:
345 char *StrAd;
346 struct addr SadAd, SadBc;
347 int len;
348
349 /* check input */
350 if( !SvOK(SvAd) ){
351 warn("addr_net: undef input\n");
352 RETVAL = &PL_sv_undef;
353 }else{
354 /* address: SV -> string */
355 StrAd = (char *) SvPV(SvAd, len);
356 /* address: string -> struct addr */
357 if( addr_aton(StrAd, &SadAd) < 0 ){
358 warn("addr_net: addr_aton: error\n");
359 RETVAL = &PL_sv_undef;
360 /* compute output */
361 }else if( addr_net(&SadAd, &SadBc) < 0 ){
362 warn("addr_net: error\n");
363 RETVAL = &PL_sv_undef;
364 }else{
365 /* broadcast: struct addr -> SV */
366 if( (StrAd = addr_ntoa((struct addr *) &SadBc)) == NULL){
367 warn("addr_net: addr_ntoa: error\n");
368 RETVAL = &PL_sv_undef;
369 }else{
370 /* 0 means Perl does strlen() itself */
371 RETVAL = newSVpv(StrAd, 0);
372 }
373 }
374 }
375 OUTPUT:
376 RETVAL
377
378 SV*
379 _obsolete_arp_add(SvProtoAddr, SvHwAddr)
380 SV *SvProtoAddr;
381 SV *SvHwAddr;
382 PROTOTYPE: $$
383 CODE:
384 arp_t *AtArp;
385 struct arp_entry SarEntry;
386 struct addr SadAddr;
387 char *StrAddr;
388 int len;
389
390 /* check input */
391 if( !SvOK(SvProtoAddr) ){
392 warn("arp_add: undef input(1)\n");
393 RETVAL = &PL_sv_undef;
394 }else if( !SvOK(SvHwAddr) ){
395 warn("arp_add: undef input(2)\n");
396 RETVAL = &PL_sv_undef;
397 }else{
398 /* open arp handler */
399 if( (AtArp = arp_open()) == NULL ){
400 warn("arp_add: arp_open: error\n");
401 RETVAL = &PL_sv_undef;
402 }else{
403
404 /* protocol address: SV -> string */
405 StrAddr = (char *) SvPV(SvProtoAddr, len);
406
407 /* protocol address: string -> struct addr */
408 if( addr_aton(StrAddr, &SadAddr) < 0 ){
409 warn("arp_add: addr_aton: error (1)\n");
410 RETVAL = &PL_sv_undef;
411 }else{
412 /* protocol address -> arp_entry */
413 memcpy(&SarEntry.arp_pa, &SadAddr, sizeof(struct addr));
414
415 /* hardware address: SV -> string */
416 StrAddr = (char *) SvPV(SvHwAddr, len);
417
418 /* hardware address: string -> struct addr */
419 if( addr_aton(StrAddr, &SadAddr) < 0 ){
420 warn("arp_add: addr_aton: error (2)\n");
421 RETVAL = &PL_sv_undef;
422 }else{
423 memcpy(&SarEntry.arp_ha, &SadAddr, sizeof(struct addr));
424
425 /* add to ARP table */
426 if( arp_add(AtArp, &SarEntry) < 0 ){
427 warn("arp_add: error\n");
428 RETVAL = &PL_sv_undef;
429 }else{
430 RETVAL = newSVnv(1);
431 }
432 }
433 }
434
435 /* close arp handler */
436 arp_close(AtArp);
437 }
438 }
439 OUTPUT:
440 RETVAL
441
442 SV*
443 _obsolete_arp_delete(SvProtoAddr)
444 SV *SvProtoAddr;
445 PROTOTYPE: $
446 CODE:
447 arp_t *AtArp;
448 struct arp_entry SarEntry;
449 struct addr SadAddr;
450 char *StrAddr;
451 int len;
452
453 /* check input */
454 if( !SvOK(SvProtoAddr) ){
455 warn("arp_delete: undef input\n");
456 RETVAL = &PL_sv_undef;
457 }else{
458 /* open arp handler */
459 if( (AtArp = arp_open()) == NULL ){
460 warn("arp_get: arp_open: error\n");
461 RETVAL = &PL_sv_undef;
462 }else{
463
464 /* convert input to string */
465 StrAddr = (char *) SvPV(SvProtoAddr, len);
466
467 /* convert input to struct addr */
468 if( addr_aton(StrAddr, &SadAddr) < 0 ){
469 warn("arp_delete: addr_aton: error\n");
470 RETVAL = &PL_sv_undef;
471 }else{
472 memcpy(&SarEntry.arp_pa, &SadAddr, sizeof(struct addr));
473
474 /* resolve protocol address with arp */
475 if( arp_delete(AtArp, &SarEntry) < 0 ){
476 /* do not warn: a request for a nonexistant address is valid */
477 RETVAL = &PL_sv_undef;
478 }else{
479 RETVAL = newSVnv(1);
480 }
481
482 }
483
484 /* close arp handler */
485 arp_close(AtArp);
486 }
487 }
488 OUTPUT:
489 RETVAL
490
491 SV*
492 _obsolete_arp_get(SvProtoAddr)
493 SV *SvProtoAddr;
494 PROTOTYPE: $
495 CODE:
496 arp_t *AtArp;
497 struct arp_entry SarEntry;
498 struct addr SadAddr;
499 char *StrAddr;
500 int len;
501
502 /* check input */
503 if( !SvOK(SvProtoAddr) ){
504 warn("arp_get: undef input\n");
505 RETVAL = &PL_sv_undef;
506 }else{
507 /* open arp handler */
508 if( (AtArp = arp_open()) == NULL ){
509 warn("arp_get: arp_open: error\n");
510 RETVAL = &PL_sv_undef;
511 }else{
512
513 /* convert input to string */
514 StrAddr = (char *) SvPV(SvProtoAddr, len);
515
516 /* convert input to struct addr */
517 if( addr_aton(StrAddr, &SadAddr) < 0 ){
518 warn("arp_get: addr_aton: error\n");
519 RETVAL = &PL_sv_undef;
520 }else{
521 memcpy(&SarEntry.arp_pa, &SadAddr, sizeof(struct addr));
522
523 /* resolve protocol address with arp */
524 if( arp_get(AtArp, &SarEntry) < 0 ){
525 /* do not warn: a request for a nonexistant address is valid */
526 RETVAL = &PL_sv_undef;
527 }else{
528
529 /* convert output to string */
530 if( (StrAddr = addr_ntoa( (struct addr *) &SarEntry.arp_ha)) == NULL){
531 warn("arp_get: addr_ntoa: error\n");
532 RETVAL = &PL_sv_undef;
533 }else{
534 /* 0 means Perl does strlen() itself */
535 RETVAL = newSVpv(StrAddr, 0);
536 }
537 }
538 }
539
540 /* close arp handler */
541 arp_close(AtArp);
542 }
543 }
544 OUTPUT:
545 RETVAL
546
547 HV *
548 _obsolete_intf_get(SvName)
549 SV *SvName;
550 PROTOTYPE: $
551 CODE:
552 HV *HvUndef;
553 intf_t *ItIntf;
554 struct intf_entry SieEntry;
555 char *StrName;
556 int len;
557
558 /* prepare undefined hash */
559 HvUndef = newHV();
560 hv_undef(HvUndef);
561
562 /* check input */
563 if( !SvOK(SvName) ){
564 warn("intf_get: undef input\n");
565 RETVAL = HvUndef;
566 }else{
567 /* open intf handler */
568 if( (ItIntf = intf_open()) == NULL ){
569 warn("intf_get: intf_open: error\n");
570 RETVAL = HvUndef;
571 }else{
572 /* name: SV -> string */
573 StrName = (char *) SvPV(SvName, len);
574
575 /* request interface */
576 SieEntry.intf_len = sizeof(SieEntry);
577 strncpy(SieEntry.intf_name, StrName, INTF_NAME_LEN);
578 if( intf_get(ItIntf, &SieEntry) < 0 ){
579 /* cannot warn, since the name may not exist */
580 RETVAL = HvUndef;
581 }else{
582 RETVAL = intf2hash(&SieEntry);
583 }
584
585 /* close intf handler */
586 intf_close(ItIntf);
587 }
588 }
589 OUTPUT:
590 RETVAL
591
592 HV *
593 _obsolete_intf_get_src(SvAddr)
594 SV *SvAddr;
595 PROTOTYPE: $
596 CODE:
597 HV *HvUndef;
598 intf_t *ItIntf;
599 struct intf_entry SieEntry;
600 struct addr SaAddr;
601 char *StrAddr;
602 int len;
603
604 /* prepare undefined hash */
605 HvUndef = newHV();
606 hv_undef(HvUndef);
607
608 /* check input */
609 if( !SvOK(SvAddr) ){
610 warn("intf_get_src: undef input\n");
611 RETVAL = HvUndef;
612 }else{
613 /* open intf handler */
614 if( (ItIntf = intf_open()) == NULL ){
615 warn("intf_get_src: intf_open: error\n");
616 RETVAL = HvUndef;
617 }else{
618 /* addr: SV -> string */
619 StrAddr = (char *) SvPV(SvAddr, len);
620
621 /* addr: string -> struct addr */
622 if( addr_aton(StrAddr, &SaAddr) < 0 ){
623 warn("intf_get_src: addr_aton: error\n");
624 RETVAL = HvUndef;
625 }else{
626 /* request interface */
627 SieEntry.intf_len = sizeof(SieEntry);
628 if( intf_get_src(ItIntf, &SieEntry, &SaAddr) < 0 ){
629 /* cannot warn, since the name may not exist */
630 RETVAL = HvUndef;
631 }else{
632 RETVAL = intf2hash(&SieEntry);
633 }
634 }
635
636 /* close intf handler */
637 intf_close(ItIntf);
638 }
639 }
640 OUTPUT:
641 RETVAL
642
643 HV *
644 _obsolete_intf_get_dst(SvAddr)
645 SV *SvAddr;
646 PROTOTYPE: $
647 CODE:
648 HV *HvUndef;
649 intf_t *ItIntf;
650 struct intf_entry SieEntry;
651 struct addr SaAddr;
652 char *StrAddr;
653 int len;
654
655 /* prepare undefined hash */
656 HvUndef = newHV();
657 hv_undef(HvUndef);
658
659 /* check input */
660 if( !SvOK(SvAddr) ){
661 warn("intf_get_dst: undef input\n");
662 RETVAL = HvUndef;
663 }else{
664 /* open intf handler */
665 if( (ItIntf = intf_open()) == NULL ){
666 warn("intf_get_dst: intf_open: error\n");
667 RETVAL = HvUndef;
668 }else{
669 /* addr: SV -> string */
670 StrAddr = (char *) SvPV(SvAddr, len);
671
672 /* addr: string -> struct addr */
673 if( addr_aton(StrAddr, &SaAddr) < 0 ){
674 warn("intf_get_dst: addr_aton: error\n");
675 RETVAL = HvUndef;
676 }else{
677 /* request interface */
678 SieEntry.intf_len = sizeof(SieEntry);
679 if( intf_get_dst(ItIntf, &SieEntry, &SaAddr) < 0 ){
680 /* cannot warn, since the name may not exist */
681 RETVAL = HvUndef;
682 }else{
683 RETVAL = intf2hash(&SieEntry);
684 }
685 }
686
687 /* close intf handler */
688 intf_close(ItIntf);
689 }
690 }
691 OUTPUT:
692 RETVAL
693
694 SV*
695 _obsolete_route_add(SvDstAddr, SvGwAddr)
696 SV *SvDstAddr;
697 SV *SvGwAddr;
698 PROTOTYPE: $$
699 CODE:
700 route_t *RtRoute;
701 struct route_entry SrtEntry;
702 struct addr SadAddr;
703 char *StrAddr;
704 int len;
705
706 /* check input */
707 if( !SvOK(SvDstAddr) ){
708 warn("route_add: undef input(1)\n");
709 RETVAL = &PL_sv_undef;
710 }else if( !SvOK(SvGwAddr) ){
711 warn("route_add: undef input(2)\n");
712 RETVAL = &PL_sv_undef;
713 }else{
714 /* open route handler */
715 if( (RtRoute = route_open()) == NULL ){
716 warn("route_add: route_open: error\n");
717 RETVAL = &PL_sv_undef;
718 }else{
719
720 /* destination address: SV -> string */
721 StrAddr = (char *) SvPV(SvDstAddr, len);
722
723 /* destination address: string -> struct addr */
724 if( addr_aton(StrAddr, &SadAddr) < 0 ){
725 warn("route_add: addr_aton: error (1)\n");
726 RETVAL = &PL_sv_undef;
727 }else{
728 /* destination address -> route_entry */
729 memcpy(&SrtEntry.route_dst, &SadAddr, sizeof(struct addr));
730
731 /* gateway address: SV -> string */
732 StrAddr = (char *) SvPV(SvGwAddr, len);
733
734 /* gateway address: string -> struct addr */
735 if( addr_aton(StrAddr, &SadAddr) < 0 ){
736 warn("route_add: addr_aton: error (2)\n");
737 RETVAL = &PL_sv_undef;
738 }else{
739 memcpy(&SrtEntry.route_gw, &SadAddr, sizeof(struct addr));
740
741 /* add to route table */
742 if( route_add(RtRoute, &SrtEntry) < 0 ){
743 warn("route_add: error\n");
744 RETVAL = &PL_sv_undef;
745 }else{
746 RETVAL = newSVnv(1);
747 }
748 }
749 }
750
751 /* close route handler */
752 route_close(RtRoute);
753 }
754 }
755 OUTPUT:
756 RETVAL
757
758 SV*
759 _obsolete_route_delete(SvDstAddr)
760 SV *SvDstAddr;
761 PROTOTYPE: $
762 CODE:
763 route_t *RtRoute;
764 struct route_entry SrtEntry;
765 struct addr SadAddr;
766 char *StrAddr;
767 int len;
768
769 /* check input */
770 if( !SvOK(SvDstAddr) ){
771 warn("route_delete: undef input\n");
772 RETVAL = &PL_sv_undef;
773 }else{
774 /* open route handler */
775 if( (RtRoute = route_open()) == NULL ){
776 warn("route_get: route_open: error\n");
777 RETVAL = &PL_sv_undef;
778 }else{
779
780 /* convert input to string */
781 StrAddr = (char *) SvPV(SvDstAddr, len);
782
783 /* convert input to struct addr */
784 if( addr_aton(StrAddr, &SadAddr) < 0 ){
785 warn("route_delete: addr_aton: error\n");
786 RETVAL = &PL_sv_undef;
787 }else{
788 memcpy(&SrtEntry.route_dst, &SadAddr, sizeof(struct addr));
789
790 /* remove route */
791 if( route_delete(RtRoute, &SrtEntry) < 0 ){
792 /* do not warn: a request for a nonexistant address is valid */
793 RETVAL = &PL_sv_undef;
794 }else{
795 RETVAL = newSVnv(1);
796 }
797
798 }
799
800 /* close route handler */
801 route_close(RtRoute);
802 }
803 }
804 OUTPUT:
805 RETVAL
806
807 SV*
808 _obsolete_route_get(SvDstAddr)
809 SV *SvDstAddr;
810 PROTOTYPE: $
811 CODE:
812 route_t *RtRoute;
813 struct route_entry SrtEntry;
814 struct addr SadAddr;
815 char *StrAddr;
816 int len;
817
818 /* check input */
819 if( !SvOK(SvDstAddr) ){
820 warn("route_get: undef input\n");
821 RETVAL = &PL_sv_undef;
822 }else{
823 /* open route handler */
824 if( (RtRoute = route_open()) == NULL ){
825 warn("route_get: route_open: error\n");
826 RETVAL = &PL_sv_undef;
827 }else{
828
829 /* convert input to string */
830 StrAddr = (char *) SvPV(SvDstAddr, len);
831
832 /* convert input to struct addr */
833 if( addr_aton(StrAddr, &SadAddr) < 0 ){
834 warn("route_get: addr_aton: error\n");
835 RETVAL = &PL_sv_undef;
836 }else{
837 memcpy(&SrtEntry.route_dst, &SadAddr, sizeof(struct addr));
838
839 /* resolve protocol address with route */
840 if( route_get(RtRoute, &SrtEntry) < 0 ){
841 /* do not warn: a request for a nonexistant address is valid */
842 RETVAL = &PL_sv_undef;
843 }else{
844
845 /* convert output to string */
846 if( (StrAddr = addr_ntoa( (struct addr *) &SrtEntry.route_gw)) == NULL){
847 warn("route_get: addr_ntoa: error\n");
848 RETVAL = &PL_sv_undef;
849 }else{
850 /* 0 means Perl does strlen() itself */
851 RETVAL = newSVpv(StrAddr, 0);
852 }
853 }
854 }
855
856 /* close route handler */
857 route_close(RtRoute);
858 }
859 }
860 OUTPUT:
861 RETVAL
862
863 #
864 # The following are the new XS implementation.
865 # I prefixed with dnet_ in order to not clash with libdnet C functions used by
866 # obsolete XS implementation.
867 #
868
869 #if defined DNET_INTF_H
870
871 IntfHandle *
872 dnet_intf_open()
873 CODE:
874 RETVAL = intf_open();
875 OUTPUT:
876 RETVAL
877
878 SV *
879 dnet_intf_get(handle, entry)
880 IntfHandle *handle
881 SV *entry
882 PREINIT:
883 char buf[1024];
884 IntfEntry *intfEntry;
885 IntfEntry *intfEntryPtr;
886 INIT:
887 intfEntry = (IntfEntry *)buf;
888 intfEntryPtr = NULL;
889 memset(buf, 0, sizeof(buf));
890 intfEntryPtr = intf_sv2c(entry, intfEntry);
891 intfEntry->intf_len = sizeof(buf);
892 CODE:
893 if (intf_get(handle, intfEntryPtr) == -1) { XSRETURN_UNDEF; }
894 else { RETVAL = intf_c2sv(intfEntry); }
895 OUTPUT:
896 RETVAL
897
898 SV *
899 dnet_intf_get_src(handle, src)
900 IntfHandle *handle
901 SV *src
902 PREINIT:
903 char buf[1024];
904 IntfEntry *intfEntry;
905 struct addr aSrc;
906 int ret;
907 INIT:
908 intfEntry = (IntfEntry *)buf;
909 memset(buf, 0, sizeof(buf));
910 intfEntry->intf_len = sizeof(buf);
911 memset(&aSrc, 0, sizeof(struct addr));
912 ret = addr_aton(SvPV(src, PL_na), &aSrc);
913 CODE:
914 if (! ret && intf_get_src(handle, intfEntry, &aSrc) == -1) {
915 XSRETURN_UNDEF;
916 }
917 else { RETVAL = intf_c2sv(intfEntry); }
918 OUTPUT:
919 RETVAL
920
921 SV *
922 dnet_intf_get_dst(handle, dst)
923 IntfHandle *handle
924 SV *dst
925 PREINIT:
926 char buf[1024];
927 struct addr aDst;
928 int ret;
929 IntfEntry *intfEntry;
930 INIT:
931 intfEntry = (IntfEntry *)buf;
932 memset(buf, 0, sizeof(buf));
933 intfEntry->intf_len = sizeof(buf);
934 memset(&aDst, 0, sizeof(struct addr));
935 ret = addr_aton(SvPV(dst, PL_na), &aDst);
936 CODE:
937 if (! ret && intf_get_dst(handle, intfEntry, &aDst) == -1) {
938 XSRETURN_UNDEF;
939 }
940 else { RETVAL = intf_c2sv(intfEntry); }
941 OUTPUT:
942 RETVAL
943
944 int
945 dnet_intf_set(handle, entry)
946 IntfHandle *handle
947 SV *entry
948 PREINIT:
949 IntfEntry *intfEntryPtr;
950 IntfEntry intfEntry;
951 INIT:
952 intfEntryPtr = NULL;
953 intfEntryPtr = intf_sv2c(entry, &intfEntry);
954 CODE:
955 if (intf_set(handle, &intfEntry) == -1) { XSRETURN_UNDEF; }
956 else { RETVAL = 1; }
957 OUTPUT:
958 RETVAL
959
960 int
961 dnet_intf_loop(handle, callback, data)
962 IntfHandle *handle
963 SV *callback
964 SV *data
965 CODE:
966 if (keepSub == (SV *)NULL)
967 keepSub = newSVsv(callback);
968 else
969 SvSetSV(keepSub, callback);
970 RETVAL = intf_loop(handle, (intf_handler)intf_callback, data);
971 OUTPUT:
972 RETVAL
973
974 IntfHandle *
975 dnet_intf_close(handle)
976 IntfHandle *handle
977 CODE:
978 RETVAL = intf_close(handle);
979 OUTPUT:
980 RETVAL
981
982 #endif
983
984 #if defined DNET_ARP_H
985
986 ArpHandle *
987 dnet_arp_open()
988 CODE:
989 RETVAL = arp_open();
990 OUTPUT:
991 RETVAL
992
993 int
994 dnet_arp_add(handle, entry)
995 ArpHandle *handle
996 SV *entry
997 PREINIT:
998 ArpEntry arpEntry;
999 ArpEntry *arpEntryPtr;
1000 INIT:
1001 arpEntryPtr = NULL;
1002 arpEntryPtr = arp_sv2c(entry, &arpEntry);
1003 CODE:
1004 RETVAL = arp_add(handle, arpEntryPtr);
1005 if (RETVAL == -1) { XSRETURN_UNDEF; }
1006 else { RETVAL = 1; }
1007 OUTPUT:
1008 RETVAL
1009
1010 int
1011 dnet_arp_delete(handle, entry)
1012 ArpHandle *handle
1013 SV *entry
1014 PREINIT:
1015 ArpEntry arpEntry;
1016 ArpEntry *arpEntryPtr;
1017 INIT:
1018 arpEntryPtr = NULL;
1019 arpEntryPtr = arp_sv2c(entry, &arpEntry);
1020 CODE:
1021 RETVAL = arp_delete(handle, arpEntryPtr);
1022 if (RETVAL == -1) { XSRETURN_UNDEF; }
1023 else { RETVAL = 1; }
1024 OUTPUT:
1025 RETVAL
1026
1027 SV *
1028 dnet_arp_get(handle, entry)
1029 ArpHandle *handle
1030 SV *entry
1031 PREINIT:
1032 ArpEntry *arpEntryPtr;
1033 ArpEntry arpEntry;
1034 INIT:
1035 arpEntryPtr = NULL;
1036 arpEntryPtr = arp_sv2c(entry, &arpEntry);
1037 CODE:
1038 if (arp_get(handle, arpEntryPtr) == -1) { XSRETURN_UNDEF; }
1039 else { RETVAL = arp_c2sv(arpEntryPtr); }
1040 OUTPUT:
1041 RETVAL
1042
1043 int
1044 dnet_arp_loop(handle, callback, data)
1045 ArpHandle *handle
1046 SV *callback
1047 SV *data
1048 CODE:
1049 if (keepSub == (SV *)NULL)
1050 keepSub = newSVsv(callback);
1051 else
1052 SvSetSV(keepSub, callback);
1053 RETVAL = arp_loop(handle, (arp_handler)arp_callback, data);
1054 OUTPUT:
1055 RETVAL
1056
1057 ArpHandle *
1058 dnet_arp_close(handle)
1059 ArpHandle *handle
1060 CODE:
1061 RETVAL = arp_close(handle);
1062 OUTPUT:
1063 RETVAL
1064
1065 #endif
1066
1067 #if defined DNET_ROUTE_H
1068
1069 RouteHandle *
1070 dnet_route_open()
1071 CODE:
1072 RETVAL = route_open();
1073 OUTPUT:
1074 RETVAL
1075
1076 int
1077 dnet_route_add(handle, entry)
1078 RouteHandle *handle
1079 SV *entry
1080 PREINIT:
1081 RouteEntry routeEntry;
1082 RouteEntry *routeEntryPtr;
1083 INIT:
1084 routeEntryPtr = NULL;
1085 routeEntryPtr = route_sv2c(entry, &routeEntry);
1086 CODE:
1087 RETVAL = route_add(handle, routeEntryPtr);
1088 if (RETVAL == -1) { XSRETURN_UNDEF; }
1089 else { RETVAL = 1; }
1090 OUTPUT:
1091 RETVAL
1092
1093 int
1094 dnet_route_delete(handle, entry)
1095 RouteHandle *handle
1096 SV *entry
1097 PREINIT:
1098 RouteEntry routeEntry;
1099 RouteEntry *routeEntryPtr;
1100 INIT:
1101 routeEntryPtr = NULL;
1102 routeEntryPtr = route_sv2c(entry, &routeEntry);
1103 CODE:
1104 RETVAL = route_delete(handle, routeEntryPtr);
1105 if (RETVAL == -1) { XSRETURN_UNDEF; }
1106 else { RETVAL = 1; }
1107 OUTPUT:
1108 RETVAL
1109
1110 SV *
1111 dnet_route_get(handle, entry)
1112 RouteHandle *handle
1113 SV *entry
1114 PREINIT:
1115 RouteEntry routeEntry;
1116 RouteEntry *routeEntryPtr;
1117 INIT:
1118 routeEntryPtr = NULL;
1119 routeEntryPtr = route_sv2c(entry, &routeEntry);
1120 CODE:
1121 if (route_get(handle, routeEntryPtr) == -1) { XSRETURN_UNDEF; }
1122 else { RETVAL = route_c2sv(routeEntryPtr); }
1123 OUTPUT:
1124 RETVAL
1125
1126 int
1127 dnet_route_loop(handle, callback, data)
1128 RouteHandle *handle
1129 SV *callback
1130 SV *data
1131 CODE:
1132 if (keepSub == (SV *)NULL)
1133 keepSub = newSVsv(callback);
1134 else
1135 SvSetSV(keepSub, callback);
1136 RETVAL = route_loop(handle, (route_handler)route_callback, data);
1137 //printf("RETVAL: %d\n", RETVAL);
1138 OUTPUT:
1139 RETVAL
1140
1141 RouteHandle *
1142 dnet_route_close(handle)
1143 RouteHandle *handle
1144 CODE:
1145 RETVAL = route_close(handle);
1146 OUTPUT:
1147 RETVAL
1148
1149 #endif
1150
1151 #if defined DNET_FW_H
1152
1153 FwHandle *
1154 dnet_fw_open()
1155 CODE:
1156 RETVAL = fw_open();
1157 OUTPUT:
1158 RETVAL
1159
1160 int
1161 dnet_fw_add(handle, rule)
1162 FwHandle *handle
1163 SV *rule
1164 PREINIT:
1165 FwRule fwRule;
1166 FwRule *fwRulePtr;
1167 INIT:
1168 fwRulePtr = NULL;
1169 fwRulePtr = fw_sv2c(rule, &fwRule);
1170 CODE:
1171 RETVAL = fw_add(handle, fwRulePtr);
1172 if (RETVAL == -1) { XSRETURN_UNDEF; }
1173 else { RETVAL = 1; }
1174 OUTPUT:
1175 RETVAL
1176
1177 int
1178 dnet_fw_delete(handle, rule)
1179 FwHandle *handle
1180 SV *rule
1181 PREINIT:
1182 FwRule fwRule;
1183 FwRule *fwRulePtr;
1184 INIT:
1185 fwRulePtr = NULL;
1186 fwRulePtr = fw_sv2c(rule, &fwRule);
1187 CODE:
1188 RETVAL = fw_delete(handle, fwRulePtr);
1189 if (RETVAL == -1) { XSRETURN_UNDEF; }
1190 else { RETVAL = 1; }
1191 OUTPUT:
1192 RETVAL
1193
1194 int
1195 dnet_fw_loop(handle, callback, data)
1196 FwHandle *handle
1197 SV *callback
1198 SV *data
1199 CODE:
1200 if (keepSub == (SV *)NULL)
1201 keepSub = newSVsv(callback);
1202 else
1203 SvSetSV(keepSub, callback);
1204 RETVAL = fw_loop(handle, (fw_handler)fw_callback, data);
1205 OUTPUT:
1206 RETVAL
1207
1208 FwHandle *
1209 dnet_fw_close(handle)
1210 FwHandle *handle
1211 CODE:
1212 RETVAL = fw_close(handle);
1213 OUTPUT:
1214 RETVAL
1215
1216 #endif
1217
1218 #if defined DNET_TUN_H
1219
1220 TunHandle *
1221 dnet_tun_open(src, dst, size)
1222 SV *src
1223 SV *dst
1224 int size
1225 INIT:
1226 struct addr aSrc;
1227 struct addr aDst;
1228 memset(&aSrc, 0, sizeof(struct addr));
1229 memset(&aDst, 0, sizeof(struct addr));
1230 CODE:
1231 if (addr_aton(SvPV(src, PL_na), &aSrc)) { XSRETURN_UNDEF; }
1232 if (addr_aton(SvPV(dst, PL_na), &aDst)) { XSRETURN_UNDEF; }
1233 RETVAL = tun_open(&aSrc, &aDst, size);
1234 OUTPUT:
1235 RETVAL
1236
1237 int
1238 dnet_tun_fileno(handle)
1239 TunHandle *handle
1240 CODE:
1241 RETVAL = tun_fileno(handle);
1242 if (RETVAL == -1) { XSRETURN_UNDEF; }
1243 OUTPUT:
1244 RETVAL
1245
1246 const char *
1247 dnet_tun_name(handle)
1248 TunHandle *handle
1249 CODE:
1250 RETVAL = tun_name(handle);
1251 if (RETVAL == NULL) { XSRETURN_UNDEF; }
1252 OUTPUT:
1253 RETVAL
1254
1255 int
1256 dnet_tun_send(handle, buf, size)
1257 TunHandle *handle
1258 SV *buf
1259 int size
1260 CODE:
1261 RETVAL = tun_send(handle, SvPV(buf, PL_na), size);
1262 if (RETVAL == -1) { XSRETURN_UNDEF; }
1263 OUTPUT:
1264 RETVAL
1265
1266 SV *
1267 dnet_tun_recv(handle, size)
1268 TunHandle *handle
1269 int size
1270 PREINIT:
1271 int read;
1272 unsigned char buf[size+1];
1273 INIT:
1274 memset(buf, 0, size+1);
1275 CODE:
1276 if ((read = tun_recv(handle, buf, size)) > 0) {
1277 RETVAL = newSVpv(buf, read);
1278 }
1279 else { XSRETURN_UNDEF; }
1280 OUTPUT:
1281 RETVAL
1282
1283 TunHandle *
1284 dnet_tun_close(handle)
1285 TunHandle *handle
1286 CODE:
1287 RETVAL = tun_close(handle);
1288 OUTPUT:
1289 RETVAL
1290
1291 #endif
1292
1293 #if defined DNET_ETH_H
1294
1295 EthHandle *
1296 dnet_eth_open(device)
1297 SV *device
1298 CODE:
1299 RETVAL = eth_open(SvPV(device, PL_na));
1300 OUTPUT:
1301 RETVAL
1302
1303 SV *
1304 dnet_eth_get(handle)
1305 EthHandle *handle
1306 PREINIT:
1307 char *addr;
1308 EthAddr a;
1309 INIT:
1310 memset(&a, 0, sizeof(EthAddr));
1311 CODE:
1312 if (eth_get(handle, &a) == -1) { XSRETURN_UNDEF; }
1313 if ((addr = eth_ntoa(&a)) == NULL) { XSRETURN_UNDEF; }
1314 else { RETVAL = newSVpv(addr, 0); }
1315 OUTPUT:
1316 RETVAL
1317
1318 int
1319 dnet_eth_set(handle, addr)
1320 EthHandle *handle
1321 SV *addr
1322 CODE:
1323 RETVAL = eth_set(handle, (const EthAddr *)SvPV(addr, PL_na));
1324 if (RETVAL == -1) { XSRETURN_UNDEF; }
1325 OUTPUT:
1326 RETVAL
1327
1328 int
1329 dnet_eth_send(handle, buf, size)
1330 EthHandle *handle
1331 SV *buf
1332 int size
1333 CODE:
1334 RETVAL = eth_send(handle, SvPV(buf, PL_na), size);
1335 if (RETVAL == -1) { XSRETURN_UNDEF; }
1336 OUTPUT:
1337 RETVAL
1338
1339 EthHandle *
1340 dnet_eth_close(handle)
1341 EthHandle *handle
1342 CODE:
1343 RETVAL = eth_close(handle);
1344 OUTPUT:
1345 RETVAL
1346
1347 #endif
1348
1349 #if defined DNET_IP_H
1350
1351 IpHandle *
1352 dnet_ip_open()
1353 CODE:
1354 RETVAL = ip_open();
1355 OUTPUT:
1356 RETVAL
1357
1358 int
1359 dnet_ip_send(handle, buf, size)
1360 IpHandle *handle
1361 SV *buf
1362 int size
1363 CODE:
1364 RETVAL = ip_send(handle, SvPV(buf, PL_na), size);
1365 if (RETVAL == -1) { XSRETURN_UNDEF; }
1366 OUTPUT:
1367 RETVAL
1368
1369 void
1370 dnet_ip_checksum(buf, size)
1371 SV *buf
1372 int size
1373 CODE:
1374 ip_checksum(SvPV(buf, PL_na), size);
1375
1376 IpHandle *
1377 dnet_ip_close(handle)
1378 IpHandle *handle
1379 CODE:
1380 RETVAL = ip_close(handle);
1381 OUTPUT:
1382 RETVAL
1383
1384 #endif
1385