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