… | |
… | |
540 | CODE: |
540 | CODE: |
541 | { |
541 | { |
542 | char buf [512]; |
542 | char buf [512]; |
543 | struct sockaddr_in sa; |
543 | struct sockaddr_in sa; |
544 | socklen_t sl = sizeof (sa); |
544 | socklen_t sl = sizeof (sa); |
545 | AV *res_av = newAV (); |
545 | AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ()); |
546 | SV *res_rv = sv_2mortal (newRV_noinc ((SV *)res_av)); |
|
|
547 | tstamp now = NOW (); |
546 | tstamp now = NOW (); |
548 | |
547 | |
549 | for (;;) |
548 | for (;;) |
550 | { |
549 | { |
551 | int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); |
550 | int len = recvfrom (icmp4_fd, buf, sizeof (buf), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); |
… | |
… | |
557 | |
556 | |
558 | int hdrlen = (iphdr->version_ihl & 15) * 4; |
557 | int hdrlen = (iphdr->version_ihl & 15) * 4; |
559 | int totlen = ntohs (iphdr->tot_len); |
558 | int totlen = ntohs (iphdr->tot_len); |
560 | |
559 | |
561 | // packet corrupt? |
560 | // packet corrupt? |
|
|
561 | if (!res_av |
562 | if (totlen > len |
562 | || totlen > len |
563 | || iphdr->protocol != IPPROTO_ICMP |
563 | || iphdr->protocol != IPPROTO_ICMP |
564 | || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) |
564 | || hdrlen < HDR_SIZE_IP4 || hdrlen + sizeof (PKT) != totlen) |
565 | continue; |
565 | continue; |
566 | |
566 | |
567 | PKT *pkt = (PKT *)(buf + hdrlen); |
567 | PKT *pkt = (PKT *)(buf + hdrlen); |
… | |
… | |
578 | av_push (av, newSVuv (pkt->payload)); |
578 | av_push (av, newSVuv (pkt->payload)); |
579 | |
579 | |
580 | av_push (res_av, newRV_noinc ((SV *)av)); |
580 | av_push (res_av, newRV_noinc ((SV *)av)); |
581 | } |
581 | } |
582 | |
582 | |
|
|
583 | if (res_av) |
583 | feed_reply (res_av); |
584 | feed_reply (res_av); |
584 | } |
585 | } |
585 | |
586 | |
586 | void |
587 | void |
587 | _recv_icmp6 (...) |
588 | _recv_icmp6 (...) |
588 | CODE: |
589 | CODE: |
589 | { |
590 | { |
590 | struct sockaddr_in6 sa; |
591 | struct sockaddr_in6 sa; |
591 | socklen_t sl = sizeof (sa); |
592 | socklen_t sl = sizeof (sa); |
592 | AV *res_av = (AV *)sv_2mortal ((SV *)newAV ()); |
593 | AV *res_av = av_len (cbs) < 0 ? 0 : (AV *)sv_2mortal ((SV *)newAV ()); |
593 | PKT pkt; |
594 | PKT pkt; |
594 | tstamp now = NOW (); |
595 | tstamp now = NOW (); |
595 | |
596 | |
596 | for (;;) |
597 | for (;;) |
597 | { |
598 | { |
598 | int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); |
599 | int len = recvfrom (icmp6_fd, &pkt, sizeof (pkt), MSG_DONTWAIT | MSG_TRUNC, &sa, &sl); |
599 | |
600 | |
600 | if (len != sizeof (PKT)) |
601 | if (len != sizeof (PKT)) |
601 | break; |
602 | break; |
602 | |
603 | |
|
|
604 | if (!res_av |
603 | if (pkt.type != ICMP6_ECHO_REPLY |
605 | || pkt.type != ICMP6_ECHO_REPLY |
604 | || pkt.id != (uint16_t) MAGIC |
606 | || pkt.id != (uint16_t) MAGIC |
605 | || pkt.seq != (uint16_t)~MAGIC |
607 | || pkt.seq != (uint16_t)~MAGIC |
606 | || !isnormal (pkt.stamp)) |
608 | || !isnormal (pkt.stamp)) |
607 | continue; |
609 | continue; |
608 | |
610 | |
… | |
… | |
612 | av_push (av, newSVuv (pkt.payload)); |
614 | av_push (av, newSVuv (pkt.payload)); |
613 | |
615 | |
614 | av_push (res_av, newRV_noinc ((SV *)av)); |
616 | av_push (res_av, newRV_noinc ((SV *)av)); |
615 | } |
617 | } |
616 | |
618 | |
|
|
619 | if (res_av) |
617 | feed_reply (res_av); |
620 | feed_reply (res_av); |
618 | } |
621 | } |
619 | |
622 | |