Annotation of embedaddon/mtr/packet/deconstruct_unix.c, revision 1.1.1.3

1.1       misho       1: /*
                      2:     mtr  --  a network diagnostic tool
                      3:     Copyright (C) 2016  Matt Kimball
                      4: 
                      5:     This program is free software; you can redistribute it and/or modify
                      6:     it under the terms of the GNU General Public License version 2 as
                      7:     published by the Free Software Foundation.
                      8: 
                      9:     This program is distributed in the hope that it will be useful,
                     10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12:     GNU General Public License for more details.
                     13: 
1.1.1.2   misho      14:     You should have received a copy of the GNU General Public License along
                     15:     with this program; if not, write to the Free Software Foundation, Inc.,
                     16:     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.1       misho      17: */
                     18: 
                     19: #include "deconstruct_unix.h"
                     20: 
                     21: #include <stdio.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
                     24: 
                     25: #include "protocols.h"
1.1.1.2   misho      26: #include "sockaddr.h"
1.1       misho      27: 
                     28: #define MAX_MPLS_LABELS 8
                     29: 
                     30: /*
                     31:     Given an ICMP id + ICMP sequence, find the match probe we've
                     32:     transmitted and if found, respond to the command which sent it
                     33: */
                     34: static
                     35: void find_and_receive_probe(
                     36:     struct net_state_t *net_state,
                     37:     const struct sockaddr_storage *remote_addr,
                     38:     struct timeval *timestamp,
                     39:     int icmp_type,
                     40:     int protocol,
                     41:     int icmp_id,
                     42:     int icmp_sequence,
                     43:     int mpls_count,
                     44:     struct mpls_label_t *mpls)
                     45: {
                     46:     struct probe_t *probe;
                     47: 
                     48:     probe = find_probe(net_state, protocol, icmp_id, icmp_sequence);
                     49:     if (probe == NULL) {
                     50:         return;
                     51:     }
                     52: 
                     53:     receive_probe(net_state, probe, icmp_type,
                     54:                   remote_addr, timestamp, mpls_count, mpls);
                     55: }
                     56: 
                     57: /*
                     58:     Handle a UDP packet received embedded in an ICMP reply.
                     59:     The sequence number identifying the probe might be in
                     60:     the source port number, the destination port number, or
                     61:     the checksum.  We'll check all three.
                     62: */
                     63: static
                     64: void handle_inner_udp_packet(
                     65:     struct net_state_t *net_state,
                     66:     const struct sockaddr_storage *remote_addr,
                     67:     int icmp_result,
1.1.1.2   misho      68:     int af,
                     69:     const void *ip,
1.1       misho      70:     const struct UDPHeader *udp,
                     71:     int udp_length,
                     72:     struct timeval *timestamp,
                     73:     int mpls_count,
                     74:     struct mpls_label_t *mpls)
                     75: {
                     76:     struct probe_t *probe;
                     77: 
                     78:     probe = find_probe(net_state, IPPROTO_UDP, 0, udp->dstport);
                     79:     if (probe == NULL) {
                     80:         probe = find_probe(net_state, IPPROTO_UDP, 0, udp->srcport);
                     81:     }
                     82:     if (probe == NULL) {
                     83:         probe = find_probe(net_state, IPPROTO_UDP, 0, udp->checksum);
                     84:     }
1.1.1.2   misho      85:     if (probe == NULL)
                     86:         return;
                     87: 
                     88:     if (probe->remote_addr.ss_family != remote_addr->ss_family)
                     89:         return;
                     90: 
                     91:     if (udp->dstport != *sockaddr_port_offset(&probe->remote_addr) )
                     92:         return;
                     93: 
                     94:     if (udp->srcport != *sockaddr_port_offset(&probe->local_addr) )
                     95:         return;
                     96: 
                     97:     void *saddr, *daddr;
                     98:     if (af == AF_INET)
                     99:     {
                    100:         saddr = &((struct IPHeader *)ip)->saddr;
                    101:         daddr = &((struct IPHeader *)ip)->daddr;
1.1.1.3 ! misho     102:     } else
1.1.1.2   misho     103:     if (af == AF_INET6)
                    104:     {
                    105:         daddr = &((struct IP6Header *)ip)->daddr;
                    106:         saddr = &((struct IP6Header *)ip)->saddr;
1.1.1.3 ! misho     107:     } else
1.1.1.2   misho     108:     {
                    109:         return;
                    110:     }
1.1       misho     111: 
1.1.1.3 ! misho     112:     if ( memcmp(sockaddr_addr_offset(&probe->remote_addr),
1.1.1.2   misho     113:                daddr,
                    114:                sockaddr_addr_size(&probe->remote_addr)) != 0 )
                    115:             return;
                    116: 
1.1.1.3 ! misho     117:     if ( memcmp(sockaddr_addr_offset(&probe->local_addr),
1.1.1.2   misho     118:            saddr,
                    119:            sockaddr_addr_size(&probe->local_addr)) != 0)
                    120:         return;
                    121: 
                    122:     /* probe is not null */
                    123:     receive_probe(net_state, probe, icmp_result,
1.1       misho     124:                       remote_addr, timestamp, mpls_count, mpls);
1.1.1.2   misho     125: }
                    126: 
                    127: void handle_error_queue_packet(
                    128:     struct net_state_t *net_state,
                    129:     const struct sockaddr_storage *remote_addr,
                    130:     int icmp_result,
                    131:     int proto,
                    132:     char *packet,
                    133:     int packet_length,
                    134:     struct timeval *timestamp)
                    135: {
                    136:     if (proto == IPPROTO_UDP) {
                    137:         handle_inner_udp_packet(net_state, remote_addr, ICMP_TIME_EXCEEDED, 0, NULL,
                    138:                 (struct UDPHeader *)packet, packet_length, timestamp, 0, NULL);
                    139:     } else if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
                    140:         const struct ICMPHeader *icmp = (struct ICMPHeader *)packet;
                    141:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    142:                                ICMP_TIME_EXCEEDED, IPPROTO_ICMP, icmp->id,
                    143:                                icmp->sequence, 0, NULL);
1.1       misho     144:     }
1.1.1.2   misho     145: 
1.1       misho     146: }
                    147: 
                    148: /*
                    149:     We've received an ICMP message with an embedded IP packet.
                    150:     We will try to determine which of our outgoing probes
                    151:     corresponds to the embedded IP packet and record the response.
                    152: */
                    153: static
                    154: void handle_inner_ip4_packet(
                    155:     struct net_state_t *net_state,
                    156:     const struct sockaddr_storage *remote_addr,
                    157:     int icmp_result,
                    158:     const struct IPHeader *ip,
                    159:     int packet_length,
                    160:     struct timeval *timestamp,
                    161:     int mpls_count,
                    162:     struct mpls_label_t *mpls)
                    163: {
                    164:     const int ip_icmp_size =
                    165:         sizeof(struct IPHeader) + sizeof(struct ICMPHeader);
                    166:     const int ip_udp_size =
                    167:         sizeof(struct IPHeader) + sizeof(struct UDPHeader);
                    168:     const int ip_tcp_size =
                    169:         sizeof(struct IPHeader) + sizeof(struct TCPHeader);
                    170:     const struct ICMPHeader *icmp;
                    171:     const struct UDPHeader *udp;
                    172:     const struct TCPHeader *tcp;
                    173:     int udp_length;
                    174: #ifdef IPPROTO_SCTP
                    175:     const int ip_sctp_size =
                    176:         sizeof(struct IPHeader) + sizeof(struct SCTPHeader);
                    177:     const struct SCTPHeader *sctp;
                    178: #endif
                    179: 
                    180:     if (ip->protocol == IPPROTO_ICMP) {
                    181:         if (packet_length < ip_icmp_size) {
                    182:             return;
                    183:         }
                    184: 
                    185:         icmp = (struct ICMPHeader *) (ip + 1);
                    186: 
                    187:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    188:                                icmp_result, IPPROTO_ICMP, icmp->id,
                    189:                                icmp->sequence, mpls_count, mpls);
                    190:     } else if (ip->protocol == IPPROTO_UDP) {
                    191:         if (packet_length < ip_udp_size) {
                    192:             return;
                    193:         }
                    194: 
                    195:         udp = (struct UDPHeader *) (ip + 1);
                    196:         udp_length = packet_length - sizeof(struct IPHeader);
                    197: 
1.1.1.2   misho     198:         handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET, ip, udp,
1.1       misho     199:                                 udp_length, timestamp, mpls_count, mpls);
                    200:     } else if (ip->protocol == IPPROTO_TCP) {
                    201:         if (packet_length < ip_tcp_size) {
                    202:             return;
                    203:         }
                    204: 
                    205:         tcp = (struct TCPHeader *) (ip + 1);
                    206: 
                    207:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    208:                                icmp_result, IPPROTO_TCP, 0, tcp->srcport,
                    209:                                mpls_count, mpls);
                    210: #ifdef IPPROTO_SCTP
                    211:     } else if (ip->protocol == IPPROTO_SCTP) {
                    212:         if (packet_length < ip_sctp_size) {
                    213:             return;
                    214:         }
                    215: 
                    216:         sctp = (struct SCTPHeader *) (ip + 1);
                    217: 
                    218:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    219:                                icmp_result, IPPROTO_SCTP, 0, sctp->srcport,
                    220:                                mpls_count, mpls);
                    221: #endif
                    222:     }
                    223: }
                    224: 
                    225: /*
                    226:     Examine the IPv6 header embedded in a returned ICMPv6 packet
                    227:     in order to match it with a probe which we previously sent.
                    228: */
                    229: static
                    230: void handle_inner_ip6_packet(
                    231:     struct net_state_t *net_state,
                    232:     const struct sockaddr_storage *remote_addr,
                    233:     int icmp_result,
                    234:     const struct IP6Header *ip,
                    235:     int packet_length,
                    236:     struct timeval *timestamp,
                    237:     int mpls_count,
                    238:     struct mpls_label_t *mpls)
                    239: {
                    240:     const int ip_icmp_size =
                    241:         sizeof(struct IP6Header) + sizeof(struct ICMPHeader);
                    242:     const int ip_udp_size =
                    243:         sizeof(struct IP6Header) + sizeof(struct UDPHeader);
                    244:     const int ip_tcp_size =
                    245:         sizeof(struct IP6Header) + sizeof(struct TCPHeader);
                    246:     const struct ICMPHeader *icmp;
                    247:     const struct UDPHeader *udp;
                    248:     const struct TCPHeader *tcp;
                    249:     int udp_length;
                    250: #ifdef IPPROTO_SCTP
                    251:     const int ip_sctp_size =
                    252:         sizeof(struct IPHeader) + sizeof(struct SCTPHeader);
                    253:     const struct SCTPHeader *sctp;
                    254: #endif
                    255: 
                    256:     if (ip->protocol == IPPROTO_ICMPV6) {
                    257:         if (packet_length < ip_icmp_size) {
                    258:             return;
                    259:         }
                    260: 
                    261:         icmp = (struct ICMPHeader *) (ip + 1);
                    262: 
                    263:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    264:                                icmp_result, IPPROTO_ICMP, icmp->id,
                    265:                                icmp->sequence, mpls_count, mpls);
                    266:     } else if (ip->protocol == IPPROTO_UDP) {
                    267:         if (packet_length < ip_udp_size) {
                    268:             return;
                    269:         }
                    270: 
                    271:         udp = (struct UDPHeader *) (ip + 1);
                    272:         udp_length = packet_length - sizeof(struct IP6Header);
                    273: 
1.1.1.2   misho     274:         handle_inner_udp_packet(net_state, remote_addr, icmp_result, AF_INET6, ip, udp,
1.1       misho     275:                                 udp_length, timestamp, mpls_count, mpls);
                    276:     } else if (ip->protocol == IPPROTO_TCP) {
                    277:         if (packet_length < ip_tcp_size) {
                    278:             return;
                    279:         }
                    280: 
                    281:         tcp = (struct TCPHeader *) (ip + 1);
                    282:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    283:                                icmp_result, IPPROTO_TCP, 0, tcp->srcport,
                    284:                                mpls_count, mpls);
                    285: #ifdef IPPROTO_SCTP
                    286:     } else if (ip->protocol == IPPROTO_SCTP) {
                    287:         if (packet_length < ip_sctp_size) {
                    288:             return;
                    289:         }
                    290: 
                    291:         sctp = (struct SCTPHeader *) (ip + 1);
                    292: 
                    293:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    294:                                icmp_result, IPPROTO_SCTP, 0, sctp->srcport,
                    295:                                mpls_count, mpls);
                    296: #endif
                    297:     }
                    298: }
                    299: 
                    300: /*  Convert an ICMP MPLS extension object into an mpls_label_t structure  */
                    301: static
                    302: int decode_mpls_object(
                    303:     struct ICMPExtensionObject *icmp_obj,
                    304:     int obj_len,
                    305:     struct mpls_label_t *mpls,
                    306:     int mpls_count)
                    307: {
                    308:     int label_bytes;
                    309:     int labels_present;
                    310:     int i;
                    311:     struct ICMPExtMPLSLabel *ext_mpls;
                    312:     struct ICMPExtMPLSLabel *ext_label;
                    313:     struct mpls_label_t *label;
                    314: 
                    315:     label_bytes = obj_len - sizeof(struct ICMPExtensionObject);
                    316:     labels_present = label_bytes / sizeof(struct ICMPExtMPLSLabel);
                    317: 
                    318:     ext_mpls = (struct ICMPExtMPLSLabel *) (icmp_obj + 1);
                    319:     for (i = 0; i < mpls_count && i < labels_present; i++) {
                    320:         ext_label = &ext_mpls[i];
                    321:         label = &mpls[i];
                    322: 
                    323:         memset(label, 0, sizeof(struct mpls_label_t));
                    324: 
                    325:         label->label =
                    326:             ext_label->label[0] << 12 |
                    327:             ext_label->label[1] << 4 | ext_label->label[2] >> 4;
1.1.1.2   misho     328:         label->traffic_class = (ext_label->label[2] & 0x0E) >> 1;
1.1       misho     329:         label->bottom_of_stack = ext_label->label[2] & 0x01;
                    330:         label->ttl = ext_label->ttl;
                    331:     }
                    332: 
                    333:     return i;
                    334: }
                    335: 
                    336: /*  Extract MPLS labels from the ICMP extension header, if present  */
                    337: static
                    338: int decode_mpls_labels(
                    339:     const struct ICMPHeader *icmp,
                    340:     int packet_length,
                    341:     struct mpls_label_t *mpls,
                    342:     int mpls_count)
                    343: {
                    344:     const int icmp_orig_icmp_ext_size =
                    345:         sizeof(struct ICMPHeader) + ICMP_ORIGINAL_DATAGRAM_MIN_SIZE +
                    346:         sizeof(struct ICMPExtensionHeader);
                    347:     char *inner_packet;
                    348:     char *icmp_object_bytes;
                    349:     struct ICMPExtensionHeader *icmp_ext;
                    350:     struct ICMPExtensionObject *icmp_obj;
                    351:     int remaining_size;
                    352:     int obj_len;
                    353: 
                    354:     if (packet_length < icmp_orig_icmp_ext_size) {
                    355:         return 0;
                    356:     }
                    357: 
                    358:     inner_packet = (char *) (icmp + 1);
                    359:     icmp_ext = (struct ICMPExtensionHeader *)
                    360:         (inner_packet + ICMP_ORIGINAL_DATAGRAM_MIN_SIZE);
                    361: 
                    362:     if ((icmp_ext->version & 0xF0) != 0x20) {
                    363:         return 0;
                    364:     }
                    365: 
                    366:     remaining_size = packet_length - icmp_orig_icmp_ext_size;
                    367:     icmp_object_bytes = (char *) (icmp_ext + 1);
                    368: 
                    369:     /*
                    370:        Iterate through the chain of extension objects, looking for
                    371:        an MPLS label extension.
                    372:      */
                    373:     while (remaining_size >= sizeof(struct ICMPExtensionObject)) {
                    374:         icmp_obj = (struct ICMPExtensionObject *) icmp_object_bytes;
                    375:         obj_len = ntohs(icmp_obj->len);
                    376: 
                    377:         if (obj_len > remaining_size) {
                    378:             return 0;
                    379:         }
                    380:         if (obj_len < sizeof(struct ICMPExtensionObject)) {
                    381:             return 0;
                    382:         }
                    383: 
                    384:         if (icmp_obj->classnum == ICMP_EXT_MPLS_CLASSNUM &&
                    385:             icmp_obj->ctype == ICMP_EXT_MPLS_CTYPE) {
                    386: 
                    387:             return decode_mpls_object(icmp_obj, obj_len, mpls, mpls_count);
                    388:         }
                    389: 
                    390:         remaining_size -= obj_len;
                    391:         icmp_object_bytes += obj_len;
                    392:     }
                    393: 
                    394:     return 0;
                    395: }
                    396: 
                    397: /*
                    398:     Decode the ICMP header received and try to find a probe which it
                    399:     is in response to.
                    400: */
                    401: static
                    402: void handle_received_icmp4_packet(
                    403:     struct net_state_t *net_state,
                    404:     const struct sockaddr_storage *remote_addr,
                    405:     const struct ICMPHeader *icmp,
                    406:     int packet_length,
                    407:     struct timeval *timestamp)
                    408: {
1.1.1.2   misho     409:     int icmp_ip_size = 0;
1.1       misho     410:     const struct IPHeader *inner_ip;
                    411:     int inner_size = packet_length - sizeof(struct ICMPHeader);
                    412:     int mpls_count;
                    413:     struct mpls_label_t mpls[MAX_MPLS_LABELS];
                    414: 
1.1.1.2   misho     415:     if (net_state->platform.ip4_socket_raw) {
                    416:         icmp_ip_size += sizeof(struct IPHeader);
                    417:     }
                    418:     icmp_ip_size += sizeof(struct ICMPHeader);
1.1       misho     419:     mpls_count =
                    420:         decode_mpls_labels(icmp, packet_length, mpls, MAX_MPLS_LABELS);
                    421: 
                    422:     /*  If we get an echo reply, our probe reached the destination host  */
                    423:     if (icmp->type == ICMP_ECHOREPLY) {
                    424:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    425:                                ICMP_ECHOREPLY, IPPROTO_ICMP, icmp->id,
                    426:                                icmp->sequence, mpls_count, mpls);
                    427:     }
                    428: 
                    429:     if (packet_length < icmp_ip_size) {
                    430:         return;
                    431:     }
                    432:     inner_ip = (struct IPHeader *) (icmp + 1);
                    433: 
                    434:     /*
                    435:        If we get a time exceeded, we got a response from an intermediate
                    436:        host along the path to our destination.
                    437:      */
                    438:     if (icmp->type == ICMP_TIME_EXCEEDED) {
                    439:         /*
                    440:            The IP packet inside the ICMP response contains our original
                    441:            IP header.  That's where we can get our original ID and
                    442:            sequence number.
                    443:          */
                    444:         handle_inner_ip4_packet(net_state, remote_addr,
                    445:                                 ICMP_TIME_EXCEEDED, inner_ip, inner_size,
                    446:                                 timestamp, mpls_count, mpls);
                    447:     }
                    448: 
                    449:     if (icmp->type == ICMP_DEST_UNREACH) {
                    450:         /*
                    451:            We'll get a ICMP_PORT_UNREACH when a non-ICMP probe
                    452:            reaches its final destination.  (Assuming that port isn't
                    453:            open on the destination host.)
                    454:          */
                    455:         if (icmp->code == ICMP_PORT_UNREACH) {
                    456:             handle_inner_ip4_packet(net_state, remote_addr,
                    457:                                     ICMP_ECHOREPLY, inner_ip, inner_size,
                    458:                                     timestamp, mpls_count, mpls);
1.1.1.2   misho     459:         } else {
                    460:             /*
                    461:                 ICMP_DEST_UNREACH subtypes other than port unreachable
                    462:                 indicate an exceptional condition, and will be reported
                    463:                 as a "no route to host" probe response.
                    464:             */
                    465:             handle_inner_ip4_packet(net_state, remote_addr,
                    466:                                     ICMP_DEST_UNREACH, inner_ip, inner_size,
                    467:                                     timestamp, mpls_count, mpls);
1.1       misho     468:         }
                    469:     }
                    470: }
                    471: 
                    472: /*
                    473:     Decode the ICMPv6 header.  The code duplication with ICMPv4 is
                    474:     unfortunate, but small details in structure size and ICMP
                    475:     constants differ.
                    476: */
                    477: static
                    478: void handle_received_icmp6_packet(
                    479:     struct net_state_t *net_state,
                    480:     const struct sockaddr_storage *remote_addr,
                    481:     const struct ICMPHeader *icmp,
                    482:     int packet_length,
                    483:     struct timeval *timestamp)
                    484: {
                    485:     const int icmp_ip_size =
                    486:         sizeof(struct ICMPHeader) + sizeof(struct IP6Header);
                    487:     const struct IP6Header *inner_ip;
                    488:     int inner_size = packet_length - sizeof(struct ICMPHeader);
                    489:     int mpls_count;
                    490:     struct mpls_label_t mpls[MAX_MPLS_LABELS];
                    491: 
                    492:     mpls_count =
                    493:         decode_mpls_labels(icmp, packet_length, mpls, MAX_MPLS_LABELS);
                    494: 
                    495:     if (icmp->type == ICMP6_ECHOREPLY) {
                    496:         find_and_receive_probe(net_state, remote_addr, timestamp,
                    497:                                ICMP_ECHOREPLY, IPPROTO_ICMP, icmp->id,
                    498:                                icmp->sequence, mpls_count, mpls);
                    499:     }
                    500: 
                    501:     if (packet_length < icmp_ip_size) {
                    502:         return;
                    503:     }
                    504:     inner_ip = (struct IP6Header *) (icmp + 1);
                    505: 
                    506:     if (icmp->type == ICMP6_TIME_EXCEEDED) {
                    507:         handle_inner_ip6_packet(net_state, remote_addr,
                    508:                                 ICMP_TIME_EXCEEDED, inner_ip, inner_size,
                    509:                                 timestamp, mpls_count, mpls);
                    510:     }
                    511: 
                    512:     if (icmp->type == ICMP6_DEST_UNREACH) {
                    513:         if (icmp->code == ICMP6_PORT_UNREACH) {
                    514:             handle_inner_ip6_packet(net_state, remote_addr,
                    515:                                     ICMP_ECHOREPLY, inner_ip, inner_size,
                    516:                                     timestamp, mpls_count, mpls);
1.1.1.2   misho     517:         } else {
                    518:             handle_inner_ip6_packet(net_state, remote_addr,
                    519:                                     ICMP_DEST_UNREACH, inner_ip, inner_size,
                    520:                                     timestamp, mpls_count, mpls);
1.1       misho     521:         }
                    522:     }
                    523: }
                    524: 
                    525: /*
                    526:     We've received a new IPv4 ICMP packet.
                    527:     We'll check to see that it is a response to one of our probes, and
                    528:     if so, report the result of the probe to our command stream.
                    529: */
                    530: void handle_received_ip4_packet(
                    531:     struct net_state_t *net_state,
                    532:     const struct sockaddr_storage *remote_addr,
                    533:     const void *packet,
                    534:     int packet_length,
                    535:     struct timeval *timestamp)
                    536: {
1.1.1.2   misho     537:     int ip_icmp_size = 0;
1.1       misho     538:     const struct IPHeader *ip;
                    539:     const struct ICMPHeader *icmp;
                    540:     int icmp_length;
                    541: 
1.1.1.2   misho     542:     if (net_state->platform.ip4_socket_raw) {
                    543:         ip_icmp_size += sizeof(struct IPHeader);
                    544:     }
                    545:     ip_icmp_size += sizeof(struct ICMPHeader);
                    546: 
1.1       misho     547:     /*  Ensure that we don't access memory beyond the bounds of the packet  */
                    548:     if (packet_length < ip_icmp_size) {
                    549:         return;
                    550:     }
                    551: 
1.1.1.2   misho     552:     if (net_state->platform.ip4_socket_raw) {
                    553:         ip = (struct IPHeader *) packet;
                    554:         if (ip->protocol != IPPROTO_ICMP) {
                    555:             return;
                    556:         }
1.1       misho     557: 
1.1.1.2   misho     558:         icmp = (struct ICMPHeader *) (ip + 1);
                    559:         icmp_length = packet_length - sizeof(struct IPHeader);
                    560:     } else {
                    561:         icmp = (struct ICMPHeader *) packet;
                    562:         icmp_length = packet_length;
                    563:     }
1.1       misho     564: 
                    565:     handle_received_icmp4_packet(net_state, remote_addr, icmp, icmp_length,
                    566:                                  timestamp);
                    567: }
                    568: 
                    569: /*
                    570:     Unlike ICMPv6 raw sockets, unlike ICMPv4, don't include the IP header
                    571:     in received packets, so we can assume the packet we got starts
                    572:     with the ICMP packet.
                    573: */
                    574: void handle_received_ip6_packet(
                    575:     struct net_state_t *net_state,
                    576:     const struct sockaddr_storage *remote_addr,
                    577:     const void *packet,
                    578:     int packet_length,
                    579:     struct timeval *timestamp)
                    580: {
                    581:     const struct ICMPHeader *icmp;
                    582: 
                    583:     icmp = (struct ICMPHeader *) packet;
                    584: 
                    585:     handle_received_icmp6_packet(net_state, remote_addr, icmp,
                    586:                                  packet_length, timestamp);
                    587: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>