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