1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef __cplusplus
8 }
9 #endif
10
11 #include "patchlevel.h"
12
13 #if PATCHLEVEL < 5
14 # ifndef PL_sv_undef
15 # define PL_sv_undef sv_undef
16 # endif
17 # ifndef PL_na
18 # define PL_na na
19 # endif
20 #endif
21
22 #ifdef _BSDRAW_
23 #define BSDFIX(a) (a)
24 #else
25 #define BSDFIX(a) htons(a)
26 #endif
27
28 #ifdef _SOLARIS_
29 #include "solaris.h"
30 #else
31 #include <sys/cdefs.h>
32 #endif
33 #include "ifaddrlist.h"
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <pcap.h>
37 #include <netinet/in.h>
38 #include <sys/time.h>
39
40
41 #ifdef _ETH_
42
43 #define ETH_ALEN 6
44
45 struct ether_header
46 {
47 u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
48 u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
49 u_int16_t ether_type; /* packet type ID field */
50 };
51
52 #endif
53
54 struct iphdr
55 {
56 #if __BYTE_ORDER == __LITTLE_ENDIAN
57 u_int8_t ihl:4;
58 u_int8_t version:4;
59 #elif __BYTE_ORDER == __BIG_ENDIAN
60 u_int8_t version:4;
61 u_int8_t ihl:4;
62 #else
63 #error "Please fix <bytesex.h>"
64 #endif
65 u_int8_t tos;
66 u_int16_t tot_len;
67 u_int16_t id;
68 u_int16_t frag_off;
69 u_int8_t ttl;
70 u_int8_t protocol;
71 u_int16_t check;
72 u_int32_t saddr;
73 u_int32_t daddr;
74 /*The options start here. */
75 };
76
77 struct tcphdr
78 {
79 u_int16_t source;
80 u_int16_t dest;
81 u_int32_t seq;
82 u_int32_t ack_seq;
83 #if __BYTE_ORDER == __LITTLE_ENDIAN
84 u_int16_t res1:4;
85 u_int16_t doff:4;
86 u_int16_t fin:1;
87 u_int16_t syn:1;
88 u_int16_t rst:1;
89 u_int16_t psh:1;
90 u_int16_t ack:1;
91 u_int16_t urg:1;
92 u_int16_t res2:2;
93 #elif __BYTE_ORDER == __BIG_ENDIAN
94 u_int16_t doff:4;
95 u_int16_t res1:4;
96 u_int16_t res2:2;
97 u_int16_t urg:1;
98 u_int16_t ack:1;
99 u_int16_t psh:1;
100 u_int16_t rst:1;
101 u_int16_t syn:1;
102 u_int16_t fin:1;
103 #else
104 #error "Adjust your <bits/endian.h> defines"
105 #endif
106 u_int16_t window;
107 u_int16_t check;
108 u_int16_t urg_ptr;
109 };
110
111 struct icmphdr
112 {
113 u_int8_t type; /* message type */
114 u_int8_t code; /* type sub-code */
115 u_int16_t checksum;
116 union
117 {
118 struct
119 {
120 u_int16_t id;
121 u_int16_t sequence;
122 } echo; /* echo datagram */
123 u_int32_t gateway; /* gateway address */
124 struct
125 {
126 u_int16_t unused;
127 u_int16_t mtu;
128 } frag; /* path mtu discovery */
129 } un;
130 };
131
132 struct udphdr {
133 u_int16_t source;
134 u_int16_t dest;
135 u_int16_t len;
136 u_int16_t check;
137 };
138
139
140
141 #define TCPHDR 20
142
143 #pragma pack(1)
144
145 typedef struct itpkt {
146 struct iphdr ih;
147 struct tcphdr th;
148 } ITPKT;
149
150 typedef struct iipkt {
151 struct iphdr ih;
152 struct icmphdr ich;
153 } IIPKT;
154
155 typedef struct iupkt {
156 struct iphdr ih;
157 struct udphdr uh;
158 } IUPKT;
159
160
161 unsigned short ip_in_cksum(struct iphdr *iph, unsigned short *ptr, int nbytes);
162 unsigned short in_cksum(unsigned short *ptr, int nbytes);
163 int rawsock(void);
164 u_long host_to_ip (char *host_name);
165 void pkt_send(int fd, unsigned char *sock, u_char *pkt, int size);
166 int linkoffset(int);
167
168 static int
not_here(s)169 not_here(s)
170 char *s;
171 {
172 croak("%s not implemented on this architecture", s);
173 return -1;
174 }
175
176 static double
constant(name,arg)177 constant(name, arg)
178 char *name;
179 int arg;
180 {
181 errno = 0;
182 switch (*name) {
183 case 'A':
184 break;
185 case 'B':
186 break;
187 case 'C':
188 break;
189 case 'D':
190 break;
191 case 'E':
192 break;
193 case 'F':
194 break;
195 case 'G':
196 break;
197 case 'H':
198 break;
199 case 'I':
200 break;
201 case 'J':
202 break;
203 case 'K':
204 break;
205 case 'L':
206 break;
207 case 'M':
208 break;
209 case 'N':
210 break;
211 case 'O':
212 break;
213 case 'P':
214 if (strEQ(name, "PCAP_ERRBUF_SIZE"))
215 #ifdef PCAP_ERRBUF_SIZE
216 return PCAP_ERRBUF_SIZE;
217 #else
218 goto not_there;
219 #endif
220 if (strEQ(name, "PCAP_VERSION_MAJOR"))
221 #ifdef PCAP_VERSION_MAJOR
222 return PCAP_VERSION_MAJOR;
223 #else
224 goto not_there;
225 #endif
226 if (strEQ(name, "PCAP_VERSION_MINOR"))
227 #ifdef PCAP_VERSION_MINOR
228 return PCAP_VERSION_MINOR;
229 #else
230 goto not_there;
231 #endif
232 break;
233 case 'Q':
234 break;
235 case 'R':
236 break;
237 case 'S':
238 break;
239 case 'T':
240 break;
241 case 'U':
242 break;
243 case 'V':
244 break;
245 case 'W':
246 break;
247 case 'X':
248 break;
249 case 'Y':
250 break;
251 case 'Z':
252 break;
253 case 'a':
254 break;
255 case 'b':
256 break;
257 case 'c':
258 break;
259 case 'd':
260 break;
261 case 'e':
262 break;
263 case 'f':
264 break;
265 case 'g':
266 break;
267 case 'h':
268 break;
269 case 'i':
270 break;
271 case 'j':
272 break;
273 case 'k':
274 break;
275 case 'l':
276 if (strEQ(name, "lib_pcap_h"))
277 #ifdef lib_pcap_h
278 return lib_pcap_h;
279 #else
280 goto not_there;
281 #endif
282 break;
283 case 'm':
284 break;
285 case 'n':
286 break;
287 case 'o':
288 break;
289 case 'p':
290 break;
291 case 'q':
292 break;
293 case 'r':
294 break;
295 case 's':
296 break;
297 case 't':
298 break;
299 case 'u':
300 break;
301 case 'v':
302 break;
303 case 'w':
304 break;
305 case 'x':
306 break;
307 case 'y':
308 break;
309 case 'z':
310 break;
311 }
312 errno = EINVAL;
313 return 0;
314
315 not_there:
316 errno = ENOENT;
317 return 0;
318 }
319
320 SV * (*ptr)(u_char*);
321
322 pcap_handler printer;
323
retref(ref)324 static SV * retref (ref)
325 u_char * ref;
326 {
327 return (SV*)ref;
328 }
329
handler(file)330 static SV * handler (file)
331 u_char * file;
332 {
333 SV * handle;
334 GV * gv;
335 handle = sv_newmortal();
336 gv = newGVgen("Net::RawIP");
337 do_open(gv, "+<&", 3, FALSE, 0, 0, PerlIO_importFILE((FILE*)file, NULL));
338 sv_setsv(handle, sv_bless(newRV_noinc((SV*)gv), gv_stashpv("Net::RawIP",1)));
339 return handle;
340 }
341
342 SV * first;
343 SV * second;
344 SV * third;
345
346 static void
call_printer(file,pkt,user)347 call_printer (file,pkt,user)
348 u_char * file;
349 struct pcap_pkthdr * pkt;
350 u_char * user;
351 {
352 dSP ;
353 PUSHMARK(sp) ;
354 sv_setsv(first,(*ptr)(file));
355 sv_setpvn(second, (char *)pkt, sizeof(struct pcap_pkthdr));
356 sv_setpvn(third, (char *)user, pkt->caplen);
357 XPUSHs(first);
358 XPUSHs(second);
359 XPUSHs(third);
360 PUTBACK ;
361 perl_call_sv((SV*)printer,G_VOID);
362 }
363
ip_opts_parse(pkt)364 static SV * ip_opts_parse(pkt)
365 SV * pkt;
366 {
367 int byte,i;
368 STRLEN size;
369 u_char * ptr;
370 AV * RETVAL;
371 byte = 0;
372 size = SvCUR(pkt);
373 ptr = (u_char *)SvPV(pkt, size);
374 RETVAL = newAV();
375 for (i=0; byte<size; i=i+3) {
376 switch (*ptr) {
377 case 0:
378 case 1:
379 av_store(RETVAL,i,newSViv(*ptr));
380 av_store(RETVAL,i+1,newSViv(1));
381 av_store(RETVAL,i+2,newSViv(0));
382 ptr++;
383 byte++;
384 break;
385 case 7:
386 case 68:
387 case 130:
388 case 131:
389 case 136:
390 case 137:
391 av_store(RETVAL,i,newSViv(*ptr));
392 av_store(RETVAL,i+1,newSViv(*(ptr+1)));
393 av_store(RETVAL,i+2,newSVpv((char*)(ptr+2),*(ptr+1)-2));
394 if (!*(ptr + 1)) {
395 ptr++;
396 byte++;
397 }
398 else {
399 byte = byte + *(ptr + 1);
400 ptr = ptr + *(ptr + 1);
401 }
402 break;
403 default:
404 ptr++;
405 byte++;
406 }
407 }
408 return newRV_noinc((SV*)RETVAL);
409 }
410
ip_opts_creat(ref)411 static SV * ip_opts_creat(ref)
412 SV * ref;
413 {
414 int len,i;
415 AV * opts;
416 SV * ip_opts;
417 char c;
418 STRLEN l;
419
420 if (SvTYPE(SvRV(ref)) == SVt_PVAV)
421 opts = (AV *)SvRV(ref);
422 else
423 croak("Not array reference\n");
424
425 ip_opts = newSVpv(SvPV((SV*)&PL_sv_undef,l),0);
426 len = av_len(opts);
427 for (i=0; i<=(len-2); i=i+3) {
428 switch (SvIV(*av_fetch(opts,i,0))) {
429 case 0:
430 case 1:
431 c = (char)SvIV(*av_fetch(opts,i,0));
432 sv_catpvn(ip_opts,&c,1);
433 break;
434 case 7:
435 case 68:
436 case 130:
437 case 131:
438 case 136:
439 case 137:
440 c = (char)SvIV(*av_fetch(opts,i,0));
441 sv_catpvn(ip_opts, &c, 1);
442 c = (char)SvIV(*av_fetch(opts,i+1,0));
443 sv_catpvn(ip_opts, &c,1);
444 sv_catpvn(ip_opts,
445 SvPV(*av_fetch(opts,i+2,0),l),
446 SvCUR(*av_fetch(opts,i+2,0)));
447 break;
448 }
449 }
450 c = 0;
451 for (i=0; i<SvCUR(ip_opts)%4; i++) {
452 sv_catpvn(ip_opts,&c,1);
453 }
454 if (SvCUR(ip_opts) > 40)
455 SvCUR_set(ip_opts,40);
456 return ip_opts;
457 }
458
459
tcp_opts_parse(pkt)460 static SV * tcp_opts_parse(pkt)
461 SV * pkt;
462 {
463 int byte,i;
464 STRLEN size;
465 u_char * ptr;
466 AV * RETVAL;
467 byte = 0;
468 size = SvCUR(pkt);
469 ptr = (u_char *)SvPV(pkt,size);
470 RETVAL = newAV();
471 for (i=0; byte<size; i=i+3) {
472 switch (*ptr) {
473 case 0:
474 case 1:
475 av_store(RETVAL, i, newSViv(*ptr));
476 av_store(RETVAL, i+1, newSViv(1));
477 av_store(RETVAL, i+2, newSViv(0));
478 ptr++;
479 byte++;
480 break;
481 case 2:
482 case 3:
483 case 4:
484 case 5:
485 case 6:
486 case 7:
487 case 8:
488 case 11:
489 case 12:
490 case 13:
491 av_store(RETVAL, i, newSViv(*ptr));
492 av_store(RETVAL, i+1, newSViv(*(ptr+1)));
493 av_store(RETVAL, i+2, newSVpv((char*)(ptr+2),*(ptr+1)-2));
494 if (!*(ptr + 1)) {
495 ptr++;
496 byte++;
497 }
498 else {
499 byte = byte + *(ptr + 1);
500 ptr = ptr + *(ptr + 1);
501 }
502 break;
503 default:
504 ptr++;
505 byte++;
506 }
507 }
508 return newRV_noinc((SV*)RETVAL);
509 }
510
tcp_opts_creat(ref)511 static SV * tcp_opts_creat(ref)
512 SV * ref;
513 {
514 int len,i;
515 AV * opts;
516 SV * ip_opts;
517 char c;
518 STRLEN l;
519
520 if (SvTYPE(SvRV(ref)) == SVt_PVAV)
521 opts = (AV *)SvRV(ref);
522 else
523 croak("Not array reference\n");
524
525 ip_opts = newSVpv(SvPV((SV*)&PL_sv_undef,l),0);
526 len = av_len(opts);
527 for (i=0; i<=(len-2); i=i+3) {
528 switch (SvIV(*av_fetch(opts,i,0))) {
529 case 0:
530 case 1:
531 c = (char)SvIV(*av_fetch(opts,i,0));
532 sv_catpvn(ip_opts,&c,1);
533 break;
534 case 2:
535 case 3:
536 case 4:
537 case 5:
538 case 6:
539 case 7:
540 case 8:
541 case 11:
542 case 12:
543 case 13:
544 c = (char)SvIV(*av_fetch(opts, i, 0));
545 sv_catpvn(ip_opts, &c, 1);
546 c = (char)SvIV(*av_fetch(opts, i+1, 0));
547 sv_catpvn(ip_opts, &c, 1);
548 sv_catpvn(ip_opts,
549 SvPV(*av_fetch(opts,i+2,0),l),
550 SvCUR(*av_fetch(opts,i+2,0)));
551 break;
552 }
553 }
554 c = 0;
555 for (i=0; i<SvCUR(ip_opts)%4; i++) {
556 sv_catpvn(ip_opts, &c, 1);
557 }
558 if (SvCUR(ip_opts) > 40)
559 SvCUR_set(ip_opts,40);
560 return ip_opts;
561 }
562
563
564 MODULE = Net::RawIP PACKAGE = Net::RawIP PREFIX = pcap_
565
566 PROTOTYPES: ENABLE
567
568 double
569 constant(name,arg)
570 char * name
571 int arg
572
573 void
574 closefd(fd)
575 int fd
576 CODE:
577 close(fd);
578
579
580 SV *
581 ip_rt_dev(addr)
582 u_int32_t addr
583 CODE:
584 #ifdef _LINUX_
585 char dev[] = "proc";
586 RETVAL = newSVpv(dev,4);
587 #endif
588 #ifdef _BPF_
589 char dev[16];
590 int len;
591 memset(dev,0,16);
592 len = ip_rt_dev(addr,dev);
593 RETVAL = newSVpv(dev,len);
594 #endif
595 #if !defined(_LINUX_) && !defined(_BPF_)
596 croak("rdev() is not implemented on this system");
597 #endif
598 OUTPUT:
599 RETVAL
600
601
602 SV *
603 timem ()
604 CODE:
605 struct timeval tv;
606 struct timezone tz;
607 tz.tz_minuteswest = 0;
608 tz.tz_dsttime = 0;
609 if ((gettimeofday(&tv,&tz) < 0)) {
610 RETVAL = newSViv(0);
611 croak("gettimeofday()");
612 }
613 else {
614 RETVAL = newSVpvf("%u.%06u",tv.tv_sec,tv.tv_usec);
615 }
616 OUTPUT:
617 RETVAL
618
619 unsigned int
620 rawsock()
621
622 #ifdef _IFLIST_
623
624 HV *
625 ifaddrlist()
626 CODE:
627 int c,i;
628 char buf[132];
629 struct ifaddrlist *al;
630 RETVAL = newHV();
631 sv_2mortal((SV*)RETVAL);
632 c = ifaddrlist(&al,buf);
633 for (i=0; i<c; i++) {
634 hv_store(RETVAL, al->device, al->len,
635 newSVpvf("%u.%u.%u.%u",
636 (al->addr & 0xff000000) >> 24,
637 (al->addr & 0x00ff0000) >> 16,
638 (al->addr & 0x0000ff00) >> 8,
639 (al->addr & 0x000000ff)
640 ),0);
641
642 al++;
643 }
644 OUTPUT:
645 RETVAL
646
647 #endif
648
649
650 #ifdef _ETH_
651
652 int
tap(device,ip,mac)653 tap(device,ip,mac)
654 char *device
655 SV *ip
656 SV *mac
657 CODE:
658 unsigned int i;
659 unsigned char m[6];
660 RETVAL = tap(device,&i,m);
661 if (RETVAL) {
662 sv_setiv(ip,i);
663 sv_setpvn(mac,(char *)m,6);
664 }
665 OUTPUT:
666 ip
667 mac
668 RETVAL
669
670 int
mac_disc(addr,mac)671 mac_disc(addr,mac)
672 unsigned int addr
673 SV *mac
674 CODE:
675 unsigned char m[6];
676 RETVAL = mac_disc(addr,m);
677 if (RETVAL) {
678 sv_setpvn(mac,(char *)m,6);
679 }
680 OUTPUT:
681 mac
682 RETVAL
683
684 void
685 send_eth_packet(fd,eth_device,pkt,flag)
686 int fd
687 char* eth_device
688 SV* pkt
689 int flag
690 CODE:
691 send_eth_packet(fd, eth_device, (char*)SvPV(pkt,PL_na), SvCUR(pkt),flag);
692
693 AV *
694 eth_parse(pkt)
695 SV * pkt
696 CODE:
697 u_char * c;
698 struct ether_header *epkt;
699 epkt = (struct ether_header *)SvPV(pkt,PL_na);
700 RETVAL = newAV();
701 sv_2mortal((SV*)RETVAL);
702 av_unshift(RETVAL,3);
703 c = (u_char*)epkt->ether_dhost;
704 av_store(RETVAL,0,
705 newSVpvf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", c[0],c[1],c[2],c[3],c[4],c[5]));
706 c = (u_char*)epkt->ether_shost;
707 av_store(RETVAL, 1,
708 newSVpvf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", c[0],c[1],c[2],c[3],c[4],c[5]));
709 av_store(RETVAL, 2,
710 newSViv(ntohs(epkt->ether_type)));
711 OUTPUT:
712 RETVAL
713
714
715 #endif
716
717 SV *
718 set_sockaddr (daddr,port)
719 unsigned int daddr
720 unsigned short port
721 CODE:
722 int size;
723 struct sockaddr_in dest_sockaddr;
724 size = sizeof(struct sockaddr_in);
725 memset(&dest_sockaddr,0,size);
726 dest_sockaddr.sin_family = AF_INET;
727 dest_sockaddr.sin_port = htons(port);
728 dest_sockaddr.sin_addr.s_addr = htonl(daddr);
729 RETVAL = newSVpv((char*)&dest_sockaddr,size);
730 OUTPUT:
731 RETVAL
732
733
734 unsigned long
735 host_to_ip (host_name)
736 char *host_name
737
738 void
739 pkt_send (fd, sock, pkt)
740 int fd
741 SV *sock
742 SV *pkt
743 CODE:
744 pkt_send (fd, (u_char *)SvPV(sock,PL_na), (u_char *)SvPV(pkt,PL_na), SvCUR(pkt));
745
746
747 AV *
748 tcp_pkt_parse(pkt)
749 SV * pkt
750 CODE:
751 u_int ipo,doff,ihl,tot_len;
752 ITPKT *pktr;
753 ipo = 0;
754 pktr = (ITPKT *)SvPV(pkt,PL_na);
755 ihl = pktr->ih.ihl;
756 tot_len = ntohs(pktr->ih.tot_len);
757 RETVAL = newAV();
758 sv_2mortal((SV*)RETVAL);
759 av_unshift(RETVAL,29);
760 av_store(RETVAL, 0, newSViv(pktr->ih.version));
761 av_store(RETVAL, 1, newSViv(pktr->ih.ihl));
762 av_store(RETVAL, 2, newSViv(pktr->ih.tos));
763 av_store(RETVAL, 3, newSViv(ntohs(pktr->ih.tot_len)));
764 av_store(RETVAL, 4, newSViv(ntohs(pktr->ih.id)));
765 av_store(RETVAL, 5, newSViv(ntohs(pktr->ih.frag_off)));
766 av_store(RETVAL, 6, newSViv(pktr->ih.ttl));
767 av_store(RETVAL, 7, newSViv(pktr->ih.protocol));
768 av_store(RETVAL, 8, newSViv(ntohs(pktr->ih.check)));
769 av_store(RETVAL, 9, newSViv(ntohl(pktr->ih.saddr)));
770 av_store(RETVAL, 10, newSViv(ntohl(pktr->ih.daddr)));
771 if (ihl > 5) {
772 av_store(RETVAL,28,
773 ip_opts_parse(sv_2mortal(newSVpv((char*)pktr + 20,ihl*4 - 20))));
774 pktr = (ITPKT *)pktr + (ihl*4 - 20);
775 ipo = 1;
776 }
777 doff = pktr->th.doff;
778 av_store(RETVAL, 11, newSViv(ntohs(pktr->th.source)));
779 av_store(RETVAL, 12, newSViv(ntohs(pktr->th.dest)));
780 av_store(RETVAL, 13, newSViv(ntohl(pktr->th.seq)));
781 av_store(RETVAL, 14, newSViv(ntohl(pktr->th.ack_seq)));
782 av_store(RETVAL, 15, newSViv(pktr->th.doff));
783 av_store(RETVAL, 16, newSViv(pktr->th.res1));
784 av_store(RETVAL, 17, newSViv(pktr->th.res2));
785 av_store(RETVAL, 18, newSViv(pktr->th.urg));
786 av_store(RETVAL, 19, newSViv(pktr->th.ack));
787 av_store(RETVAL, 20, newSViv(pktr->th.psh));
788 av_store(RETVAL, 21, newSViv(pktr->th.rst));
789 av_store(RETVAL, 22, newSViv(pktr->th.syn));
790 av_store(RETVAL, 23, newSViv(pktr->th.fin));
791 av_store(RETVAL, 24, newSViv(ntohs(pktr->th.window)));
792 av_store(RETVAL, 25, newSViv(ntohs(pktr->th.check)));
793 av_store(RETVAL, 26, newSViv(ntohs(pktr->th.urg_ptr)));
794 if (doff > 5) {
795 if (!ipo) {
796 av_store(RETVAL, 28, newSViv(0));
797 }
798 av_store(RETVAL, 29,
799 tcp_opts_parse(sv_2mortal(newSVpv((char*)pktr+40,doff*4-20))));
800 pktr = (ITPKT *)pktr + (doff*4 - 20);
801 }
802 av_store(RETVAL, 27, newSVpv(((char*)&pktr->th.urg_ptr+2),
803 tot_len - (4*ihl + doff*4)));
804 OUTPUT:
805 RETVAL
806
807 AV *
808 icmp_pkt_parse(pkt)
809 SV * pkt
810 CODE:
811 u_int ihl,tot_len;
812 IIPKT *pktr;
813 pktr = (IIPKT *)SvPV(pkt,PL_na);
814 ihl = pktr->ih.ihl;
815 tot_len = ntohs(pktr->ih.tot_len);
816 RETVAL = newAV();
817 sv_2mortal((SV*)RETVAL);
818 av_unshift(RETVAL,20);
819 av_store(RETVAL, 0, newSViv(pktr->ih.version));
820 av_store(RETVAL, 1, newSViv(pktr->ih.ihl));
821 av_store(RETVAL, 2, newSViv(pktr->ih.tos));
822 av_store(RETVAL, 3, newSViv(ntohs(pktr->ih.tot_len)));
823 av_store(RETVAL, 4, newSViv(ntohs(pktr->ih.id)));
824 av_store(RETVAL, 5, newSViv(ntohs(pktr->ih.frag_off)));
825 av_store(RETVAL, 6, newSViv(pktr->ih.ttl));
826 av_store(RETVAL, 7, newSViv(pktr->ih.protocol));
827 av_store(RETVAL, 8, newSViv(ntohs(pktr->ih.check)));
828 av_store(RETVAL, 9, newSViv(ntohl(pktr->ih.saddr)));
829 av_store(RETVAL, 10, newSViv(ntohl(pktr->ih.daddr)));
830 if (ihl > 5) {
831 av_store(RETVAL, 20,
832 ip_opts_parse(sv_2mortal(newSVpv((char*)pktr + 20,ihl*4 - 20))));
833 pktr = (IIPKT *)pktr + (ihl*4 - 20);
834 }
835 av_store(RETVAL, 11, newSViv(pktr->ich.type));
836 av_store(RETVAL, 12, newSViv(pktr->ich.code));
837 av_store(RETVAL, 13, newSViv(ntohs(pktr->ich.checksum)));
838 av_store(RETVAL, 14, newSViv(pktr->ich.un.gateway));
839 av_store(RETVAL, 15, newSViv(pktr->ich.un.echo.id));
840 av_store(RETVAL, 16, newSViv(pktr->ich.un.echo.sequence));
841 av_store(RETVAL, 17, newSViv(pktr->ich.un.frag.unused));
842 av_store(RETVAL, 18, newSViv(pktr->ich.un.frag.mtu));
843 av_store(RETVAL, 19, newSVpv(((char*)&pktr->ich.un.frag.mtu+2),
844 tot_len - (4*ihl + 8)));
845 OUTPUT:
846 RETVAL
847
848 AV *
849 generic_pkt_parse(pkt)
850 SV * pkt
851 CODE:
852 u_int ihl,tot_len;
853 struct iphdr *pktr;
854 pktr = (struct iphdr *)SvPV(pkt,PL_na);
855 ihl = pktr->ihl;
856 tot_len = ntohs(pktr->tot_len);
857 RETVAL = newAV();
858 sv_2mortal((SV*)RETVAL);
859 av_store(RETVAL, 0, newSViv(pktr->version));
860 av_store(RETVAL, 1, newSViv(pktr->ihl));
861 av_store(RETVAL, 2, newSViv(pktr->tos));
862 av_store(RETVAL, 3, newSViv(ntohs(pktr->tot_len)));
863 av_store(RETVAL, 4, newSViv(ntohs(pktr->id)));
864 av_store(RETVAL, 5, newSViv(ntohs(pktr->frag_off)));
865 av_store(RETVAL, 6, newSViv(pktr->ttl));
866 av_store(RETVAL, 7, newSViv(pktr->protocol));
867 av_store(RETVAL, 8, newSViv(ntohs(pktr->check)));
868 av_store(RETVAL, 9, newSViv(ntohl(pktr->saddr)));
869 av_store(RETVAL, 10, newSViv(ntohl(pktr->daddr)));
870 if (ihl > 5) {
871 av_store(RETVAL,12,
872 ip_opts_parse(sv_2mortal(newSVpv((char*)pktr + 20,ihl*4 - 20))));
873 pktr = pktr + (ihl*4 - 20);
874 }
875 av_store(RETVAL, 11, newSVpv(((char*)pktr+20), tot_len - 4*ihl));
876 OUTPUT:
877 RETVAL
878
879
880 AV *
881 udp_pkt_parse(pkt)
882 SV * pkt
883 CODE:
884 u_int ihl,tot_len;
885 IUPKT *pktr;
886 pktr = (IUPKT *)SvPV(pkt,PL_na);
887 ihl = pktr->ih.ihl;
888 tot_len = ntohs(pktr->ih.tot_len);
889 RETVAL = newAV();
890 sv_2mortal((SV*)RETVAL);
891 av_unshift(RETVAL, 16);
892 av_store(RETVAL, 0, newSViv(pktr->ih.version));
893 av_store(RETVAL, 1, newSViv(pktr->ih.ihl));
894 av_store(RETVAL, 2, newSViv(pktr->ih.tos));
895 av_store(RETVAL, 3, newSViv(ntohs(pktr->ih.tot_len)));
896 av_store(RETVAL, 4, newSViv(ntohs(pktr->ih.id)));
897 av_store(RETVAL, 5, newSViv(ntohs(pktr->ih.frag_off)));
898 av_store(RETVAL, 6, newSViv(pktr->ih.ttl));
899 av_store(RETVAL, 7, newSViv(pktr->ih.protocol));
900 av_store(RETVAL, 8, newSViv(ntohs(pktr->ih.check)));
901 av_store(RETVAL, 9, newSViv(ntohl(pktr->ih.saddr)));
902 av_store(RETVAL, 10, newSViv(ntohl(pktr->ih.daddr)));
903 if (ihl > 5) {
904 av_store(RETVAL, 16,
905 ip_opts_parse(sv_2mortal(newSVpv((char*)pktr + 20,ihl*4 - 20))));
906 pktr = pktr + (ihl*4 - 20);
907 }
908 av_store(RETVAL, 11, newSViv(ntohs(pktr->uh.source)));
909 av_store(RETVAL, 12, newSViv(ntohs(pktr->uh.dest)));
910 av_store(RETVAL, 13, newSViv(ntohs(pktr->uh.len)));
911 av_store(RETVAL, 14, newSViv(ntohs(pktr->uh.check)));
912 av_store(RETVAL, 15, newSVpv(((char*)&pktr->uh.check+2),
913 tot_len - (4*ihl + 8)));
914 OUTPUT:
915 RETVAL
916
917 SV *
918 udp_pkt_creat(p)
919 SV * p
920 CODE:
921 int opt,iplen;
922 SV * ip_opts;
923 u_char * ptr;
924 AV * pkt;
925 IUPKT piu;
926 u_char *piur;
927 opt = 0;
928 iplen = 20;
929 if (SvTYPE(SvRV(p)) == SVt_PVAV)
930 pkt = (AV *)SvRV(p);
931 else
932 croak("Not array reference\n");
933 piu.ih.version = SvIV(*av_fetch(pkt,0,0));
934 piu.ih.ihl = SvIV(*av_fetch(pkt,1,0));
935 piu.ih.tos = SvIV(*av_fetch(pkt,2,0));
936 piu.ih.tot_len = BSDFIX(SvIV(*av_fetch(pkt,3,0)));
937 if (!piu.ih.tot_len)
938 piu.ih.tot_len = BSDFIX(iplen + 8 + SvCUR(*av_fetch(pkt,15,0)));
939 piu.ih.id = htons(SvIV(*av_fetch(pkt,4,0)));
940 piu.ih.frag_off = BSDFIX(SvIV(*av_fetch(pkt,5,0)));
941 piu.ih.ttl = SvIV(*av_fetch(pkt,6,0));
942 piu.ih.protocol = SvIV(*av_fetch(pkt,7,0));
943 piu.ih.check = htons(SvIV(*av_fetch(pkt,8,0)));
944 piu.ih.saddr = htonl(SvIV(*av_fetch(pkt,9,0)));
945 piu.ih.daddr = htonl(SvIV(*av_fetch(pkt,10,0)));
946 if (!piu.ih.check)
947 piu.ih.check = in_cksum((unsigned short *)&piu,iplen);
948 piu.uh.source = htons(SvIV(*av_fetch(pkt,11,0)));
949 piu.uh.dest = htons(SvIV(*av_fetch(pkt,12,0)));
950 piu.uh.len = htons(SvIV(*av_fetch(pkt,13,0)));
951 if (!piu.uh.len)
952 piu.uh.len = htons(8 + SvCUR(*av_fetch(pkt,15,0)));
953 piu.uh.check = htons(SvIV(*av_fetch(pkt,14,0)));
954 if (av_fetch(pkt,16,0)) {
955 if (SvROK(*av_fetch(pkt,16,0))) {
956 opt++;
957 ip_opts = ip_opts_creat(*av_fetch(pkt,16,0));
958 piu.ih.ihl = 5 + SvCUR(ip_opts)/4;
959 piu.ih.tot_len = BSDFIX(4*piu.ih.ihl + 8 + SvCUR(*av_fetch(pkt,15,0)));
960 iplen = 4*piu.ih.ihl;
961 piu.ih.check = 0;
962 ptr = (u_char*)safemalloc(iplen + 8);
963 memcpy(ptr,(u_char*)&piu,20);
964 memcpy(ptr+20,SvPV(ip_opts,PL_na),SvCUR(ip_opts));
965 memcpy(ptr+20+SvCUR(ip_opts),(u_char*)&piu + 20,8);
966 ((struct iphdr*)ptr)->check = in_cksum((unsigned short *)ptr,iplen);
967 RETVAL = newSVpv((char*)ptr, sizeof(IUPKT)+SvCUR(ip_opts));
968 sv_catsv(RETVAL, *av_fetch(pkt,15,0));
969 Safefree(ptr);
970 sv_2mortal(ip_opts);
971 }
972 }
973 if (!opt) {
974 RETVAL = newSVpv((char*)&piu,sizeof(IUPKT));
975 sv_catsv(RETVAL,*av_fetch(pkt,15,0));
976 }
977 if (!piu.uh.check) {
978 piur = (u_char*) SvPV(RETVAL, PL_na);
979 ((struct udphdr*)(piur + iplen))->check =
980 ip_in_cksum((struct iphdr *)piur,
981 (unsigned short *)(piur + iplen),
982 8 + SvCUR(*av_fetch(pkt,15,0)));
983 sv_setpvn(RETVAL, (char*)piur, iplen + 8 + SvCUR(*av_fetch(pkt,15,0)));
984 }
985 OUTPUT:
986 RETVAL
987
988 # This assembles an ICMP packet based on the data passed in as an
989 # array reference from the Perl module. Populating this are with
990 # comments as I try to understand the code better so I'll remember
991 # what I thought each bit did.
992 # Steve Bonds
993
994 SV *
995 icmp_pkt_creat(p)
996 SV * p
997 CODE:
998 int opt,iplen;
999 SV * ip_opts;
1000 u_char * ptr;
1001 AV * pkt;
1002 IIPKT pii;
1003 u_char *piir;
1004 opt = 0;
1005 iplen = 20;
1006 if (SvTYPE(SvRV(p)) == SVt_PVAV)
1007 /* pkt allows for easy access in C to the original parameter, p.
1008 Steve Bonds */
1009 pkt = (AV *)SvRV(p);
1010 else
1011 croak("Not array reference\n");
1012
1013 /* Populate the C pii ICMP packet structure with information from "pkt", which
1014 is the C char pointer to the array reference passed in. The perlguts
1015 man page recommends checking that this returns non-null before calling
1016 SvIV on it, probably to follow the Second Commandment of C:
1017
1018 Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.
1019
1020 (http://web.archive.org/web/19961109205914/http://www.lysator.liu.se/c/ten-commandments.html)
1021
1022 however, it would appear that the original author didn't and I don't want to
1023 make too many changes yet, so I'll pretend I didn't see it for now...
1024
1025 Steve Bonds */
1026 pii.ih.version = SvIV(*av_fetch(pkt,0,0));
1027 pii.ih.ihl = SvIV(*av_fetch(pkt,1,0));
1028 pii.ih.tos = SvIV(*av_fetch(pkt,2,0));
1029 pii.ih.tot_len = BSDFIX(SvIV(*av_fetch(pkt,3,0)));
1030 if (!pii.ih.tot_len)
1031 pii.ih.tot_len = BSDFIX(iplen + 8 + SvCUR(*av_fetch(pkt,19,0)));
1032 pii.ih.id = htons(SvIV(*av_fetch(pkt,4,0)));
1033 pii.ih.frag_off = BSDFIX(SvIV(*av_fetch(pkt,5,0)));
1034 pii.ih.ttl = SvIV(*av_fetch(pkt,6,0));
1035 pii.ih.protocol = SvIV(*av_fetch(pkt,7,0));
1036 pii.ih.check = htons(SvIV(*av_fetch(pkt,8,0)));
1037 pii.ih.saddr = htonl(SvIV(*av_fetch(pkt,9,0)));
1038 pii.ih.daddr = htonl(SvIV(*av_fetch(pkt,10,0)));
1039 if (!pii.ih.check)
1040 pii.ih.check = in_cksum((unsigned short *)&pii,iplen);
1041
1042 /* We're done with the basic IP header assembly into the pii
1043 structure. Move on to the ICMP header specifics. Steve Bonds */
1044
1045 pii.ich.type = SvIV(*av_fetch(pkt,11,0));
1046 pii.ich.code = SvIV(*av_fetch(pkt,12,0));
1047 pii.ich.checksum = htons(SvIV(*av_fetch(pkt,13,0)));
1048 pii.ich.un.gateway = SvIV(*av_fetch(pkt,14,0));
1049
1050 /* Array index 20 is the "data" area of the ICMP packet. av_fetch only
1051 returns a scalar so the data area must be one, which explains why it
1052 didn't work so great when I used an array reference here based on my
1053 incorrect understanding of the POD docs. Steve Bonds */
1054 if (av_fetch(pkt,20,0)) {
1055 if (SvROK(*av_fetch(pkt,20,0))) {
1056 opt++;
1057
1058 /* I don't understand why this module calls an internal parsing function
1059 on a raw data field supplied by the user. This may or may not
1060 associate with an actual IP structure, depending on what the
1061 user of this module decides. It appears that this is done to
1062 get the proper packet length for the IP header, but this could
1063 also be done based on the scalar length of the raw data area
1064 itself (SvCUR).
1065
1066 Why wouldn't the sum of these work for the total IP packet length:
1067 + IP header (20)
1068 + ICMP header (8)
1069 - type (1)
1070 - code (1)
1071 - checksum (2)
1072 - id or unused (2)
1073 - sequence or mtu (2)
1074 + ICMP data (variable length)
1075
1076 Finding the total length shouldn't require any decoding of the ICMP
1077 data area. Doing so just gives this module additional places to
1078 either break/crash or mangle the intended data on its way out.
1079
1080 In the interest of not breaking the module until I understand it better,
1081 leave it alone for now.
1082
1083 Steve Bonds */
1084 ip_opts = ip_opts_creat(*av_fetch(pkt,20,0));
1085 pii.ih.ihl = 5 + SvCUR(ip_opts)/4;
1086 iplen = 4*pii.ih.ihl;
1087
1088 /* Array index 19 is the MTU or Sequence. SvCUR returns the length of that scalar.
1089 Steve Bonds */
1090 pii.ih.tot_len = BSDFIX(iplen + 8 + SvCUR(*av_fetch(pkt,19,0)));
1091 pii.ih.check = 0;
1092
1093 /* Create a place to copy the pii structure for rebuilding the checksum.
1094 Steve Bonds */
1095 ptr = (u_char*)safemalloc(iplen + 8);
1096 /* Copy the 20 byte IP header in */
1097 memcpy(ptr,(u_char*)&pii,20);
1098
1099 /* Either this is a bug or I don't understand something going on here.
1100 ip_opts is derived above from field 20 of "pkt" which is the
1101 user-supplied data area of the ICMP packet they want to send.
1102 This data area is supposed to be an IP packet, but since they
1103 can set it to any arbitrary string of bytes, it doesn't necessarily
1104 have to be. So it looks to me like we just joined the 20 byte IP
1105 header with the 8 bytes ip_opts creates from the user data area.
1106 I would instead have expected this to be the 8 bytes of ICMP
1107 packet header we created above. Steve Bonds */
1108 memcpy(ptr+20,SvPV(ip_opts,PL_na),SvCUR(ip_opts));
1109
1110 /* Here's the 8 bytes we created above getting copied in. I would have
1111 expected this line to be before the above line. */
1112 memcpy(ptr+20+SvCUR(ip_opts),(u_char*)&pii + 20,8);
1113
1114 /* Re-build a valid IP checksum for our packet. */
1115 ((struct iphdr*)ptr)->check = in_cksum((unsigned short *)ptr,iplen);
1116
1117 /* Create a new scalar that will contain the string value contained
1118 in our temporary spot *ptr. This in essence becomes a packed
1119 string value in perl when it gets sent back. Steve Bonds */
1120 RETVAL = newSVpv((char*)ptr, sizeof(IIPKT)+SvCUR(ip_opts));
1121
1122 /* Toss field 19 from the original array (MTU/Sequence) onto
1123 the end of the RETVAL scalar created above. Alas, these are
1124 2-byte values so these need to be converted to proper network
1125 byte order before they will be valid. This looks like the
1126 bug I came here to find.
1127
1128 I think it may be simpler to convert this to network byte order
1129 via Perl before it gets passed in to this code so as to minimize
1130 the changes needed inside this harder-to-follow .xs file.
1131
1132 Steve Bonds */
1133 sv_catsv(RETVAL, *av_fetch(pkt, 19, 0));
1134 Safefree(ptr);
1135 sv_2mortal(ip_opts);
1136 }
1137 }
1138 if (!opt) {
1139 RETVAL = newSVpv((char*)&pii,sizeof(IIPKT));
1140 sv_catsv(RETVAL,*av_fetch(pkt,19,0));
1141 }
1142 if (!pii.ich.checksum) {
1143 piir = (u_char*) SvPV(RETVAL,PL_na);
1144 ((struct icmphdr*)(piir + iplen))->checksum =
1145 in_cksum((unsigned short *)(piir + iplen),8 + SvCUR(*av_fetch(pkt,19,0)));
1146 sv_setpvn(RETVAL,(char*)piir,iplen + 8 + SvCUR(*av_fetch(pkt,19,0)));
1147 }
1148 OUTPUT:
1149 RETVAL
1150
1151 SV *
1152 generic_pkt_creat(p)
1153 SV * p
1154 CODE:
1155 int opt,iplen;
1156 SV * ip_opts;
1157 AV * pkt;
1158 struct iphdr ih;
1159 u_char *pigr;
1160 opt = 0;
1161 iplen = 20;
1162
1163 if (SvTYPE(SvRV(p)) == SVt_PVAV)
1164 pkt = (AV *)SvRV(p);
1165 else
1166 croak("Not array reference\n");
1167
1168 ih.version = SvIV(*av_fetch(pkt,0,0));
1169 ih.ihl = SvIV(*av_fetch(pkt,1,0));
1170 ih.tos = SvIV(*av_fetch(pkt,2,0));
1171 ih.tot_len = BSDFIX(SvIV(*av_fetch(pkt,3,0)));
1172 if (!ih.tot_len)
1173 ih.tot_len = BSDFIX(iplen + SvCUR(*av_fetch(pkt,11,0)));
1174 ih.id = htons(SvIV(*av_fetch(pkt,4,0)));
1175 ih.frag_off = BSDFIX(SvIV(*av_fetch(pkt,5,0)));
1176 ih.ttl = SvIV(*av_fetch(pkt,6,0));
1177 ih.protocol = SvIV(*av_fetch(pkt,7,0));
1178 ih.check = htons(SvIV(*av_fetch(pkt,8,0)));
1179 ih.saddr = htonl(SvIV(*av_fetch(pkt,9,0)));
1180 ih.daddr = htonl(SvIV(*av_fetch(pkt,10,0)));
1181 if (!ih.check)
1182 ih.check = in_cksum((unsigned short *)&ih,iplen);
1183 if (av_fetch(pkt,12,0)) {
1184 if (SvROK(*av_fetch(pkt,12,0))) {
1185 opt++;
1186 ip_opts = ip_opts_creat(*av_fetch(pkt,12,0));
1187 if (ih.ihl <= 5)
1188 ih.ihl = 5 + SvCUR(ip_opts)/4;
1189 iplen = 20 + SvCUR(ip_opts);
1190 if (!ih.tot_len)
1191 ih.tot_len = BSDFIX(20 + SvCUR(ip_opts) + SvCUR(*av_fetch(pkt,11,0)));
1192 ih.check = 0;
1193 RETVAL = newSVpv((char*)&ih,20);
1194 sv_catsv(RETVAL,ip_opts);
1195 pigr = (u_char*) SvPV(RETVAL,PL_na);
1196 ((struct iphdr*)pigr)->check = in_cksum((unsigned short *)pigr,iplen);
1197 sv_setpvn(RETVAL,(char*)pigr,iplen);
1198 sv_catsv(RETVAL,*av_fetch(pkt,11,0));
1199 sv_2mortal(ip_opts);
1200 }
1201 }
1202 if (!opt) {
1203 RETVAL = newSVpv((char*)&ih,iplen);
1204 sv_catsv(RETVAL,*av_fetch(pkt,11,0));
1205 }
1206 OUTPUT:
1207 RETVAL
1208
1209 SV *
1210 tcp_pkt_creat(p)
1211 SV * p
1212 CODE:
1213 int ipo,opt,iplen;
1214 AV * pkt;
1215 SV * ip_opts;
1216 SV * tcp_opts;
1217 u_char * ptr;
1218 u_char * tptr;
1219 ITPKT pit;
1220 u_char *pitr;
1221 ipo = 0;
1222 opt = 0;
1223 iplen = 20;
1224 if (SvTYPE(SvRV(p)) == SVt_PVAV)
1225 pkt = (AV *)SvRV(p);
1226 else
1227 croak("Not array reference\n");
1228 pit.ih.version = SvIV(*av_fetch(pkt,0,0));
1229 pit.ih.ihl = SvIV(*av_fetch(pkt,1,0));
1230 pit.ih.tos = SvIV(*av_fetch(pkt,2,0));
1231 pit.ih.tot_len = BSDFIX(SvIV(*av_fetch(pkt,3,0)));
1232 if (!pit.ih.tot_len)
1233 pit.ih.tot_len = BSDFIX(iplen + TCPHDR + SvCUR(*av_fetch(pkt,27,0)));
1234 pit.ih.id = htons(SvIV(*av_fetch(pkt,4,0)));
1235 pit.ih.frag_off = BSDFIX(SvIV(*av_fetch(pkt,5,0)));
1236 pit.ih.ttl = SvIV(*av_fetch(pkt,6,0));
1237 pit.ih.protocol = SvIV(*av_fetch(pkt,7,0));
1238 pit.ih.check = htons(SvIV(*av_fetch(pkt,8,0)));
1239 pit.ih.saddr = htonl(SvIV(*av_fetch(pkt,9,0)));
1240 pit.ih.daddr = htonl(SvIV(*av_fetch(pkt,10,0)));
1241 if (!pit.ih.check)
1242 pit.ih.check = in_cksum((unsigned short *)&pit,iplen);
1243 pit.th.source = htons(SvIV(*av_fetch(pkt,11,0)));
1244 pit.th.dest = htons(SvIV(*av_fetch(pkt,12,0)));
1245 pit.th.seq = htonl(SvIV(*av_fetch(pkt,13,0)));
1246 pit.th.ack_seq = htonl(SvIV(*av_fetch(pkt,14,0)));
1247 pit.th.doff = SvIV(*av_fetch(pkt,15,0));
1248 pit.th.res1 = SvIV(*av_fetch(pkt,16,0));
1249 pit.th.res2 = SvIV(*av_fetch(pkt,17,0));
1250 pit.th.urg = SvIV(*av_fetch(pkt,18,0));
1251 pit.th.ack = SvIV(*av_fetch(pkt,19,0));
1252 pit.th.psh = SvIV(*av_fetch(pkt,20,0));
1253 pit.th.rst = SvIV(*av_fetch(pkt,21,0));
1254 pit.th.syn = SvIV(*av_fetch(pkt,22,0));
1255 pit.th.fin = SvIV(*av_fetch(pkt,23,0));
1256 pit.th.window = htons(SvIV(*av_fetch(pkt,24,0)));
1257 pit.th.check = htons(SvIV(*av_fetch(pkt,25,0)));
1258 pit.th.urg_ptr = htons(SvIV(*av_fetch(pkt,26,0)));
1259 if (av_fetch(pkt,28,0)) {
1260 if(SvROK(*av_fetch(pkt,28,0))) {
1261 opt++;
1262 ip_opts = ip_opts_creat(*av_fetch(pkt,28,0));
1263 pit.ih.ihl = 5 + SvCUR(ip_opts)/4;
1264 pit.ih.tot_len = BSDFIX(4*pit.ih.ihl + TCPHDR + SvCUR(*av_fetch(pkt,27,0)));
1265 iplen = 4*pit.ih.ihl;
1266 pit.ih.check = 0;
1267 ptr = (u_char*)safemalloc(4*pit.ih.ihl + TCPHDR);
1268 memcpy(ptr,(u_char*)&pit,20);
1269 memcpy(ptr+20,SvPV(ip_opts,PL_na),SvCUR(ip_opts));
1270 memcpy(ptr+20+SvCUR(ip_opts),(u_char*)&pit + 20,TCPHDR);
1271 ((struct iphdr*)ptr)->check = in_cksum((unsigned short *)ptr,4*pit.ih.ihl);
1272 RETVAL = newSVpv((char*)ptr, sizeof(ITPKT)+SvCUR(ip_opts));
1273 sv_catsv(RETVAL,*av_fetch(pkt,27,0));
1274 Safefree(ptr);
1275 sv_2mortal(ip_opts);
1276 ipo = 1;
1277 }
1278 if (av_fetch(pkt,29,0)) {
1279 if (SvROK(*av_fetch(pkt,29,0))) {
1280 opt++;
1281 tcp_opts = tcp_opts_creat(*av_fetch(pkt,29,0));
1282 if (ipo) {
1283 ptr = (u_char *)SvPV(RETVAL,PL_na);
1284 tptr = (u_char*)safemalloc(SvCUR(RETVAL) + SvCUR(tcp_opts) -
1285 SvCUR(*av_fetch(pkt,27,0)));
1286 ((struct iphdr*)ptr)->tot_len = BSDFIX(SvCUR(RETVAL) + SvCUR(tcp_opts));
1287 ((struct iphdr*)ptr)->check = 0;
1288 ((struct iphdr*)ptr)->check = in_cksum((unsigned short *)ptr,iplen);
1289 ((struct tcphdr*)(ptr + iplen))->doff = 5 + SvCUR(tcp_opts)/4;
1290 memcpy(tptr,ptr,SvCUR(RETVAL)-SvCUR(*av_fetch(pkt,27,0)));
1291 memcpy(tptr+(SvCUR(RETVAL)-SvCUR(*av_fetch(pkt,27,0))),
1292 SvPV(tcp_opts,PL_na),SvCUR(tcp_opts));
1293 sv_setpvn(RETVAL, (char *)tptr, SvCUR(RETVAL) + SvCUR(tcp_opts) -
1294 SvCUR(*av_fetch(pkt,27,0)));
1295 sv_catsv(RETVAL, *av_fetch(pkt,27,0));
1296 }
1297 else {
1298 pit.ih.tot_len = BSDFIX(40+SvCUR(tcp_opts)+SvCUR(*av_fetch(pkt,27,0)));
1299 pit.ih.check = 0;
1300 pit.ih.check = in_cksum((unsigned short *)&pit,iplen);
1301 pit.th.doff = 5 + SvCUR(tcp_opts)/4;
1302 tptr = (u_char*)safemalloc(40+SvCUR(tcp_opts));
1303 memcpy(tptr,&pit,40);
1304 memcpy(tptr+40,SvPV(tcp_opts,PL_na),SvCUR(tcp_opts));
1305 RETVAL = newSVpv((char*)tptr, 40+SvCUR(tcp_opts));
1306 sv_catsv(RETVAL, *av_fetch(pkt,27,0));
1307 }
1308 Safefree(tptr);
1309 sv_2mortal(tcp_opts);
1310 }
1311 }
1312 }
1313 if (!opt) {
1314 RETVAL = newSVpv((char*)&pit,sizeof(ITPKT));
1315 sv_catsv(RETVAL,*av_fetch(pkt,27,0));
1316 }
1317 if (!pit.th.check) {
1318 pitr = (u_char *)SvPV(RETVAL,PL_na);
1319 ((struct tcphdr*)(pitr + iplen))->check =
1320 ip_in_cksum((struct iphdr *)pitr,(unsigned short *)(pitr + iplen),
1321 4*((struct tcphdr*)(pitr + iplen))->doff +
1322 SvCUR(*av_fetch(pkt,27,0)));
1323 sv_setpvn(RETVAL,(char*)pitr,iplen+
1324 4*((struct tcphdr*)(pitr + iplen))->doff + SvCUR(*av_fetch(pkt,27,0)));
1325 }
1326 OUTPUT:
1327 RETVAL
1328
1329 pcap_t *
1330 open_live(device,snaplen,promisc,to_ms,ebuf)
1331 char *device
1332 int snaplen
1333 int promisc
1334 int to_ms
1335 char * ebuf
1336 CODE:
1337 ebuf = (char*)safemalloc(PCAP_ERRBUF_SIZE);
1338 RETVAL = pcap_open_live(device, snaplen, promisc, to_ms, ebuf);
1339 Safefree(ebuf);
1340 OUTPUT:
1341 ebuf
1342 RETVAL
1343
1344 pcap_t *
1345 open_offline(fname,ebuf)
1346 char *fname
1347 char *ebuf
1348 CODE:
1349 ebuf = (char*)safemalloc(PCAP_ERRBUF_SIZE);
1350 RETVAL = pcap_open_offline(fname,ebuf);
1351 Safefree(ebuf);
1352 OUTPUT:
1353 ebuf
1354 RETVAL
1355
1356 SV *
1357 pcap_dump_open(p,fname)
1358 pcap_t *p
1359 char *fname
1360 CODE:
1361 RETVAL = newSViv((unsigned long)pcap_dump_open(p,fname));
1362 OUTPUT:
1363 RETVAL
1364
1365 char *
1366 lookupdev(ebuf)
1367 char *ebuf
1368 CODE:
1369 ebuf = (char*)safemalloc(PCAP_ERRBUF_SIZE);
1370 RETVAL = pcap_lookupdev(ebuf);
1371 Safefree(ebuf);
1372 OUTPUT:
1373 ebuf
1374 RETVAL
1375
1376 int
1377 lookupnet(device,netp,maskp,ebuf)
1378 char *device
1379 bpf_u_int32 netp
1380 bpf_u_int32 maskp
1381 char *ebuf
1382 CODE:
1383 ebuf = (char*)safemalloc(PCAP_ERRBUF_SIZE);
1384 RETVAL = pcap_lookupnet(device,&netp,&maskp,ebuf);
1385 Safefree(ebuf);
1386 OUTPUT:
1387 netp
1388 maskp
1389 ebuf
1390 RETVAL
1391
1392 void
1393 dump(ptr,pkt,user)
1394 SV * ptr
1395 SV * pkt
1396 SV * user
1397 CODE:
1398 pcap_dump((u_char*)PerlIO_findFILE(IoOFP(sv_2io(ptr))),
1399 (struct pcap_pkthdr*)(SvPV(pkt,PL_na)),
1400 (u_char*)(SvPV(user,PL_na)));
1401
1402 int
1403 dispatch(p,cnt,print,user)
1404 pcap_t *p
1405 int cnt
1406 pcap_handler print
1407 SV * user
1408 CODE:
1409 printer = print;
1410 if (!SvROK(user) && SvOK(user)) {
1411 user = (SV *) SvIV(user);
1412 ptr = &handler;
1413 }
1414 else {
1415 ptr = &retref;
1416 }
1417 first = newSViv(0);
1418 second = newSViv(0);
1419 third = newSViv(0);
1420 RETVAL = pcap_dispatch(p,cnt,(pcap_handler)&call_printer,(u_char*)user);
1421 OUTPUT:
1422 RETVAL
1423
1424 int
1425 loop(p,cnt,print,user)
1426 pcap_t *p
1427 int cnt
1428 pcap_handler print
1429 SV *user
1430 CODE:
1431 printer = print;
1432 if (!SvROK(user) && SvOK(user)) {
1433 user = (SV *)SvIV(user);
1434 ptr = &handler;
1435 }
1436 else {
1437 ptr = &retref;
1438 }
1439 first = newSViv(0);
1440 second = newSViv(0);
1441 third = newSViv(0);
1442 RETVAL = pcap_loop(p,cnt,(pcap_handler)&call_printer,(u_char*)user);
1443 OUTPUT:
1444 RETVAL
1445
1446
1447 int
1448 compile(p,fp,str,optimize,netmask)
1449 pcap_t * p
1450 struct bpf_program *fp
1451 char *str
1452 int optimize
1453 unsigned int netmask
1454 CODE:
1455 fp = (struct bpf_program *)safemalloc(sizeof(struct bpf_program));
1456 RETVAL = pcap_compile(p,fp,str,optimize,netmask);
1457 OUTPUT:
1458 fp
1459 RETVAL
1460
1461 int
1462 linkoffset(p)
1463 pcap_t * p
1464 CODE:
1465 RETVAL = linkoffset(pcap_datalink(p));
1466 OUTPUT:
1467 RETVAL
1468
1469 int
1470 pcap_setfilter(p,fp)
1471 pcap_t *p
1472 struct bpf_program *fp
1473 OUTPUT:
1474 RETVAL
1475
1476 SV *
1477 next(p,h)
1478 pcap_t *p
1479 SV *h
1480 CODE:
1481 STRLEN len;
1482 u_char * hdr;
1483 const u_char * next;
1484 len = sizeof(struct pcap_pkthdr);
1485 if (!SvOK(h)) {
1486 sv_setpv(h,"new");
1487 SvGROW(h,len) ;
1488 }
1489 hdr = (u_char *)SvPV(h,len) ;
1490 next = pcap_next(p,(struct pcap_pkthdr*)hdr);
1491 if (next)
1492 RETVAL = newSVpv((char *)next,((struct pcap_pkthdr*)hdr)->caplen);
1493 else
1494 RETVAL = newSViv(0);
1495 sv_setpvn(h,(char *)hdr,len);
1496 OUTPUT:
1497 h
1498 RETVAL
1499
1500
1501
1502 int
1503 pcap_datalink(p)
1504 pcap_t *p
1505 OUTPUT:
1506 RETVAL
1507
1508 int
1509 pcap_snapshot(p)
1510 pcap_t *p
1511 OUTPUT:
1512 RETVAL
1513
1514 int
1515 pcap_is_swapped(p)
1516 pcap_t *p
1517 OUTPUT:
1518 RETVAL
1519
1520 int
1521 pcap_major_version(p)
1522 pcap_t *p
1523 OUTPUT:
1524 RETVAL
1525
1526 int
1527 pcap_minor_version(p)
1528 pcap_t *p
1529 OUTPUT:
1530 RETVAL
1531
1532 int
1533 stat(p,ps)
1534 pcap_t *p
1535 u_char *ps
1536 CODE:
1537 ps = safemalloc(sizeof(struct pcap_stat));
1538 RETVAL = pcap_stats(p,(struct pcap_stat*)ps);
1539 Safefree(ps);
1540 OUTPUT:
1541 ps
1542 RETVAL
1543
1544
1545 int
1546 pcap_fileno(p)
1547 pcap_t *p
1548 OUTPUT:
1549 RETVAL
1550
1551
1552 void
1553 pcap_perror(p,prefix)
1554 pcap_t *p
1555 char *prefix
1556
1557 SV *
1558 pcap_geterr(p)
1559 pcap_t *p
1560 CODE:
1561 RETVAL = newSVpv(pcap_geterr(p),0);
1562 OUTPUT:
1563 RETVAL
1564
1565
1566 SV *
1567 pcap_strerror(error)
1568 int error
1569 CODE:
1570 RETVAL = newSVpv(pcap_strerror(error),0);
1571 OUTPUT:
1572 RETVAL
1573
1574 void
1575 pcap_close(p)
1576 pcap_t *p
1577
1578
1579 void
1580 pcap_dump_close(p)
1581 pcap_dumper_t *p
1582
1583
1584
1585 FILE *
1586 pcap_file(p)
1587 pcap_t *p
1588 OUTPUT:
1589 RETVAL
1590
1591