The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/uipc_mbufdebug.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: uipc_mbufdebug.c,v 1.7 2018/10/18 05:44:19 msaitoh Exp $       */
    2 
    3 /*
    4  * Copyright (C) 2017 Internet Initiative Japan Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   26  * POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __KERNEL_RCSID(0, "$NetBSD: uipc_mbufdebug.c,v 1.7 2018/10/18 05:44:19 msaitoh Exp $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/proc.h>
   35 #include <sys/malloc.h>
   36 #include <sys/mbuf.h>
   37 
   38 #include <net/if.h>
   39 #include <net/if_ether.h>
   40 #include <net/ppp_defs.h>
   41 #include <net/if_arp.h>
   42 
   43 #include <netinet/in.h>
   44 #include <netinet/in_systm.h>
   45 #include <netinet/ip.h>
   46 #include <netinet/ip_icmp.h>
   47 #include <netinet/ip6.h>
   48 #include <netinet/icmp6.h>
   49 #include <netinet/if_inarp.h>
   50 #include <netinet/tcp.h>
   51 #include <netinet/udp.h>
   52 
   53 #define EXAMINE_HEX_LIMIT 128
   54 #define EXAMINE_HEX_COL 4
   55 
   56 /* mbuf operations without change of mbuf chain */
   57 static int m_peek_data(const struct mbuf *, int, int, void *);
   58 static unsigned int m_peek_len(const struct mbuf *, const char *);
   59 
   60 /* utility */
   61 static char *str_ethaddr(const uint8_t *);
   62 static char *str_ipaddr(const struct in_addr *);
   63 static char *str_ip6addr(const struct in6_addr *);
   64 static const char *str_ipproto(const uint8_t);
   65 
   66 /* header structure for some protocol */
   67 struct pppoehdr {
   68         uint8_t vertype;
   69         uint8_t code;
   70         uint16_t session;
   71         uint16_t plen;
   72 } __attribute__((__packed__));
   73 
   74 struct pppoetag {
   75         uint16_t tag;
   76         uint16_t len;
   77 } __attribute__((__packed__));
   78 
   79 #define PPPOE_TAG_EOL 0x0000
   80 #define PPPOE_CODE_PADI         0x09    /* Active Discovery Initiation */
   81 #define PPPOE_CODE_PADO         0x07    /* Active Discovery Offer */
   82 #define PPPOE_CODE_PADR         0x19    /* Active Discovery Request */
   83 #define PPPOE_CODE_PADS         0x65    /* Active Discovery Session confirmation */
   84 #define PPPOE_CODE_PADT         0xA7    /* Active Discovery Terminate */
   85 
   86 struct ppp_header {
   87         uint8_t address;
   88         uint8_t control;
   89         uint16_t protocol;
   90 } __attribute__((__packed__));
   91 
   92 #define CISCO_MULTICAST         0x8f    /* Cisco multicast address */
   93 #define CISCO_UNICAST           0x0f    /* Cisco unicast address */
   94 #define CISCO_KEEPALIVE         0x8035  /* Cisco keepalive protocol */
   95 
   96 #ifndef NELEMS
   97 #define NELEMS(elem) ((sizeof(elem))/(sizeof((elem)[0])))
   98 #endif
   99 
  100 static int
  101 m_peek_data(const struct mbuf *m, int off, int len, void *vp)
  102 {
  103         unsigned int count;
  104         char *cp = vp;
  105 
  106         if (off < 0 || len < 0)
  107                 return -1;
  108 
  109         while (off > 0) {
  110                 if (m == 0)
  111                         return -1;
  112                 if (off < m->m_len)
  113                         break;
  114                 off -= m->m_len;
  115                 m = m->m_next;
  116         }
  117         while (len > 0) {
  118                 if (m == 0)
  119                         return -1;
  120                 count = uimin(m->m_len - off, len);
  121                 memcpy(cp, mtod(m, char *) + off, count);
  122                 len -= count;
  123                 cp += count;
  124                 off = 0;
  125                 m = m->m_next;
  126         }
  127 
  128         return 0;
  129 }
  130 
  131 static unsigned int
  132 m_peek_len(const struct mbuf *m, const char *modif)
  133 {
  134         const struct mbuf *m0;
  135         unsigned int pktlen;
  136         bool opt_c = false;
  137         unsigned char ch;
  138 
  139         while (modif && (ch = *(modif++)) != '\0') {
  140                 switch (ch) {
  141                 case 'c':
  142                         opt_c = true;
  143                         break;
  144                 }
  145         }
  146 
  147         if (opt_c == true)
  148                 return m->m_len;
  149 
  150         if ((m->m_flags & M_PKTHDR) != 0)
  151                 return m->m_pkthdr.len;
  152 
  153         pktlen = 0;
  154         for (m0 = m; m0 != NULL; m0 = m0->m_next)
  155                 pktlen += m0->m_len;
  156 
  157         return pktlen;
  158 }
  159 
  160 static char *
  161 str_ethaddr(const uint8_t *ap)
  162 {
  163         static char buf[3 * ETHER_ADDR_LEN];
  164 
  165         return ether_snprintf(buf, sizeof(buf), ap);
  166 }
  167 
  168 static char *
  169 str_ipaddr(const struct in_addr *ap)
  170 {
  171         static char buf[INET_ADDRSTRLEN];
  172 
  173         return IN_PRINT(buf, ap);
  174 }
  175 
  176 static char *
  177 str_ip6addr(const struct in6_addr *ap)
  178 {
  179         static char buf[INET6_ADDRSTRLEN];
  180 
  181         return IN6_PRINT(buf, ap);
  182 }
  183 
  184 static const char *
  185 str_ipproto(const uint8_t proto)
  186 {
  187 
  188         switch (proto) {
  189         case IPPROTO_HOPOPTS:
  190                 return ("IPv6 Hop-by-Hop");
  191                 break;
  192         case IPPROTO_TCP:
  193                 return("TCP");
  194                 break;
  195         case IPPROTO_UDP:
  196                 return("UDP");
  197                 break;
  198         case IPPROTO_ICMP:
  199                 return("ICMP");
  200                 break;
  201         case IPPROTO_IGMP:
  202                 return("IGMP");
  203                 break;
  204         case IPPROTO_ESP:
  205                 return("ESP");
  206                 break;
  207         case IPPROTO_AH:
  208                 return("AH");
  209                 break;
  210         case IPPROTO_IPV6_ICMP:
  211                 return("ICMP6");
  212         default:
  213                 return("unknown");
  214                 break;
  215         }
  216 
  217         /* not reached */
  218         return NULL;
  219 }
  220 
  221 void
  222 m_examine_ether(const struct mbuf *m, int off, const char *modif,
  223     void (*pr)(const char *, ...))
  224 {
  225         struct ether_header eh;
  226         unsigned int pktlen;
  227 
  228         pktlen = m_peek_len(m, modif) - off;
  229         if (pktlen < sizeof(eh)) {
  230                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  231                     pktlen, sizeof(eh));
  232                 return m_examine_hex(m, off, modif, pr);
  233         }
  234 
  235         if (m_peek_data(m, off, sizeof(eh), (void *)(&eh)) < 0) {
  236                 (*pr)("%s: cannot read header\n", __func__);
  237                 return m_examine_hex(m, off, modif, pr);
  238         }
  239         off += sizeof(eh);
  240 
  241         (*pr)("ETHER: DST = %s\n", str_ethaddr(eh.ether_dhost));
  242         (*pr)("ETHER: SRC = %s\n", str_ethaddr(eh.ether_shost));
  243 
  244         (*pr)("ETHER: TYPE = 0x%04x(", ntohs(eh.ether_type));
  245         switch (ntohs(eh.ether_type)) {
  246         case ETHERTYPE_PPPOE:
  247                 (*pr)("PPPoE)\n");
  248                 return m_examine_pppoe(m, off, modif, pr);
  249                 break;
  250         case ETHERTYPE_ARP:
  251                 (*pr)("ARP)\n");
  252                 return m_examine_arp(m, off, modif, pr);
  253                 break;
  254         case ETHERTYPE_IP:
  255                 (*pr)("IPv4)\n");
  256                 return m_examine_ip(m, off, modif, pr);
  257                 break;
  258         case ETHERTYPE_IPV6:
  259                 (*pr)("IPv6)\n");
  260                 return m_examine_ip6(m, off, modif, pr);
  261                 break;
  262         default:
  263                 (*pr)("unknown)\n");
  264                 break;
  265         }
  266 
  267         return m_examine_hex(m, off, modif, pr);
  268 }
  269 
  270 void
  271 m_examine_pppoe(const struct mbuf *m, int off, const char *modif,
  272     void (*pr)(const char *, ...))
  273 {
  274         struct pppoehdr ph;
  275         struct pppoetag pt;
  276         unsigned int pktlen;
  277         uint8_t vt;
  278 
  279         pktlen = m_peek_len(m, modif) - off;
  280         if (pktlen < sizeof(ph)) {
  281                 (*pr)("%s: too short mbuf chain (%u, %u)\n", __func__,
  282                     pktlen, sizeof(ph));
  283                 return m_examine_hex(m, off, modif, pr);
  284         }
  285 
  286         if (m_peek_data(m, off, sizeof(ph), (void *)(&ph)) < 0) {
  287                 (*pr)("%s: cannot read header\n", __func__);
  288                 return m_examine_hex(m, off, modif, pr);
  289         }
  290         off += sizeof(ph);
  291 
  292         while (off + sizeof(pt) > pktlen) {
  293                 if (m_peek_data(m, off, sizeof(pt), (void *)(&pt)) < 0) {
  294                         (*pr)("%s: cannot read header\n", __func__);
  295                         return m_examine_hex(m, off, modif, pr);
  296                 }
  297                 off += sizeof(pt);
  298 
  299                 if (ntohs(pt.tag) == PPPOE_TAG_EOL)
  300                         break;
  301                 off += ntohs(pt.len);
  302         }
  303 
  304         vt = ph.vertype;
  305 
  306         (*pr)("PPPoE: Version = %u\n", ((vt >> 4) & 0xff));
  307         (*pr)("PPPoE: Type = %u\n", (vt & 0xff));
  308         (*pr)("PPPoE: Code = %u(", ph.code);
  309         switch (ph.code) {
  310         case 0:
  311                 (*pr)("DATA");
  312                 break;
  313         case PPPOE_CODE_PADI:
  314                 (*pr)("PADI");
  315                 break;
  316         case PPPOE_CODE_PADO:
  317                 (*pr)("PADO");
  318                 break;
  319         case PPPOE_CODE_PADS:
  320                 (*pr)("PADS");
  321                 break;
  322         case PPPOE_CODE_PADT:
  323                 (*pr)("PADT");
  324                 break;
  325         default:
  326                 (*pr)("unknown");
  327                 break;
  328         }
  329         (*pr)(")\n");
  330 
  331         (*pr)("PPPoE: Session = 0x%04x\n", ntohs(ph.session));
  332         (*pr)("PPPoE: Payload Length = %u\n", ntohs(ph.plen));
  333 
  334         switch (ph.code) {
  335         case PPPOE_CODE_PADI:
  336         case PPPOE_CODE_PADO:
  337         case PPPOE_CODE_PADS:
  338         case PPPOE_CODE_PADT:
  339                 (*pr)("No parser for PPPoE control frame.\n");
  340                 return m_examine_hex(m, off, modif, pr);
  341                 break;
  342         }
  343 
  344         if (ph.code != 0) {
  345                 (*pr)("Unknown PPPoE code.\n");
  346                 return m_examine_hex(m, off, modif, pr);
  347         }
  348 
  349         return m_examine_ppp(m, off, modif, pr);
  350 }
  351 
  352 void
  353 m_examine_ppp(const struct mbuf *m, int off, const char *modif,
  354     void (*pr)(const char *, ...))
  355 {
  356         struct ppp_header h;
  357         unsigned int pktlen;
  358         uint16_t protocol;
  359 
  360         pktlen = m_peek_len(m, modif) - off;
  361         if (pktlen < sizeof(h)) {
  362                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  363                     pktlen, sizeof(h));
  364                 return m_examine_hex(m, off, modif, pr);
  365         }
  366 
  367         if (m_peek_data(m, off, sizeof(h), (void *)(&h)) < 0) {
  368                 (*pr)("%s: cannot read header\n", __func__);
  369                 return m_examine_hex(m, off, modif, pr);
  370         }
  371         off += sizeof(h);
  372 
  373         protocol = ntohs(h.protocol);
  374 
  375         (*pr)("SPPP: Address = %d(", h.address);
  376         switch (h.address) {
  377         case PPP_ALLSTATIONS:
  378                 (*pr)("ALLSTATIONS)\n");
  379                 (*pr)("SPPP: Protocol = %d(", protocol);
  380                 switch (protocol) {
  381                 case PPP_LCP:
  382                         (*pr)("LCP)\n");
  383                         break;
  384                 case PPP_PAP:
  385                         (*pr)("PAP)\n");
  386                         break;
  387                 case PPP_CHAP:
  388                         (*pr)("CHAP)\n");
  389                         break;
  390                 case PPP_IPCP:
  391                         (*pr)("IPCP)\n");
  392                         break;
  393                 case PPP_IPV6CP:
  394                         (*pr)("IPV6CP)\n");
  395                         break;
  396                 case PPP_IP:
  397                         (*pr)("IP)\n");
  398                         return m_examine_ip(m, off, modif, pr);
  399                         break;
  400                 case PPP_IPV6:
  401                         (*pr)("IPv6)\n");
  402                         return m_examine_ip6(m, off, modif, pr);
  403                         break;
  404                 default:
  405                         (*pr)("unknown)\n");
  406                         break;
  407                 }
  408                 break;
  409         case CISCO_MULTICAST:
  410         case CISCO_UNICAST:
  411                 if (h.address == CISCO_MULTICAST)
  412                         (*pr)("MULTICAST)\n");
  413                 else
  414                         (*pr)("UNICAST)\n");
  415 
  416                 (*pr)("SPPP: Protocol = %d(", protocol);
  417                 switch (protocol) {
  418                 case CISCO_KEEPALIVE:
  419                         (*pr)("Keepalive)\n");
  420                         break;
  421                 case ETHERTYPE_IP:
  422                         (*pr)("IP)\n");
  423                         return m_examine_ip(m, off, modif, pr);
  424                         break;
  425                 case ETHERTYPE_IPV6:
  426                         (*pr)("IPv6)\n");
  427                         return m_examine_ip6(m, off, modif, pr);
  428                         break;
  429                 default:
  430                         (*pr)("unknown)\n");
  431                         break;
  432                 }
  433                 break;
  434         default:
  435                 (*pr)("unknown)\n", h.address);
  436                 break;
  437         }
  438 
  439         (*pr)("No parser for address %d, protocol %d\n", h.address, protocol);
  440         return m_examine_hex(m, off, modif, pr);
  441 }
  442 
  443 void
  444 m_examine_arp(const struct mbuf *m, int off, const char *modif,
  445     void (*pr)(const char *, ...))
  446 {
  447         unsigned int pktlen;
  448         struct arphdr ar;
  449         uint16_t hrd, op;
  450         struct in_addr isaddr, itaddr;
  451         uint8_t esaddr[ETHER_ADDR_LEN], etaddr[ETHER_ADDR_LEN];
  452 
  453         pktlen = m_peek_len(m, modif) - off;
  454         if (pktlen < sizeof(ar)) {
  455                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  456                     pktlen, sizeof(ar));
  457                 return m_examine_hex(m, off, modif, pr);
  458         }
  459 
  460         if (m_peek_data(m, off, sizeof(ar), (void *)(&ar)) < 0) {
  461                 (*pr)("%s: cannot read header\n", __func__);
  462                 return m_examine_hex(m, off, modif, pr);
  463         }
  464         off += sizeof(ar);
  465 
  466         hrd = ntohs(ar.ar_hrd);
  467         (*pr)("ARP: AddressType = %u(", hrd);
  468         switch (hrd) {
  469         case ARPHRD_ETHER:
  470                 (*pr)("ETHER)\n");
  471                 break;
  472         case ARPHRD_IEEE802:
  473                 (*pr)("IEEE802)\n");
  474                 break;
  475         default:
  476                 (*pr)("unknown)\n");
  477                 return m_examine_hex(m, off, modif, pr);
  478                 break;
  479         }
  480         (*pr)("ARP: Protocol Address Format = %u\n", ntohs(ar.ar_pro));
  481         (*pr)("ARP: Protocol Address Length = %u\n", ar.ar_pln);
  482         (*pr)("ARP: H/W Address Length = %u\n", ar.ar_hln);
  483         op = ntohs(ar.ar_op);
  484         (*pr)("ARP: Operation = %u(", op);
  485         switch (op) {
  486         case ARPOP_REQUEST:
  487                 (*pr)("REQUEST)\n");
  488                 break;
  489         case ARPOP_REPLY:
  490                 (*pr)("REPLY)\n");
  491                 break;
  492         case ARPOP_REVREQUEST:
  493                 (*pr)("REVREQUEST)\n");
  494                 break;
  495         case ARPOP_REVREPLY:
  496                 (*pr)("REVREPLY)\n");
  497                 break;
  498         case ARPOP_INVREQUEST:
  499                 (*pr)("INVREQUEST)\n");
  500                 break;
  501         case ARPOP_INVREPLY:
  502                 (*pr)("INVREPLY)\n");
  503                 break;
  504         }
  505 
  506         if (ar.ar_hln == 0 || ar.ar_pln == 0 ||
  507             ar.ar_hln != sizeof(esaddr) || ar.ar_pln != sizeof(isaddr)) {
  508                 (*pr)("Cannot parse.\n");
  509                 return m_examine_hex(m, off, modif, pr);
  510         }
  511 
  512         if (m_peek_data(m, off, sizeof(esaddr), (void *)(esaddr)) < 0) {
  513                 (*pr)("Cannot read payload\n");
  514                 return m_examine_hex(m, off, modif, pr);
  515         }
  516         off += sizeof(esaddr);
  517         (*pr)("ARP: Ether Src = %s\n", str_ethaddr(esaddr));
  518 
  519         if (m_peek_data(m, off, sizeof(isaddr), (void *)(&isaddr)) < 0) {
  520                 (*pr)("Cannot read payload\n");
  521                 return m_examine_hex(m, off, modif, pr);
  522         }
  523         off += sizeof(isaddr);
  524         (*pr)("ARP: IP Src = %s\n", str_ipaddr(&isaddr));
  525 
  526         if (m_peek_data(m, off, sizeof(etaddr), (void *)(etaddr)) < 0) {
  527                 (*pr)("Cannot read payload\n");
  528                 return m_examine_hex(m, off, modif, pr);
  529         }
  530         off += sizeof(etaddr);
  531         (*pr)("ARP: Ether Tgt = %s\n", str_ethaddr(etaddr));
  532 
  533         if (m_peek_data(m, off, sizeof(itaddr), (void *)(&itaddr)) < 0) {
  534                 (*pr)("Cannot read payload\n");
  535                 return m_examine_hex(m, off, modif, pr);
  536         }
  537         off += sizeof(itaddr);
  538         (*pr)("ARP: IP Tgt = %s\n", str_ipaddr(&itaddr));
  539 
  540         return m_examine_hex(m, off, modif, pr);
  541 }
  542 
  543 void
  544 m_examine_ip(const struct mbuf *m, int off, const char *modif,
  545     void (*pr)(const char *, ...))
  546 {
  547         unsigned int pktlen;
  548         struct ip ip;
  549         uint16_t offset;
  550 
  551         pktlen = m_peek_len(m, modif) - off;
  552         if (pktlen < sizeof(ip)) {
  553                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  554                     pktlen, sizeof(ip));
  555                 return m_examine_hex(m, off, modif, pr);
  556         }
  557 
  558         if (m_peek_data(m, off, sizeof(ip), (void *)(&ip)) < 0) {
  559                 (*pr)("%s: cannot read header\n", __func__);
  560                 return m_examine_hex(m, off, modif, pr);
  561         }
  562         off += sizeof(ip);
  563 
  564         (*pr)("IP: Version = %u\n", ip.ip_v);
  565         (*pr)("IP: Header Length = %u\n", (ip.ip_hl << 2));
  566         (*pr)("IP: ToS = 0x%02x\n", ip.ip_tos);
  567         (*pr)("IP: Packet Length = %u\n", ntohs(ip.ip_len));
  568         (*pr)("IP: ID = %u\n", ntohs(ip.ip_id));
  569         offset = ntohs(ip.ip_off);
  570         (*pr)("IP: Offset = %u\n", (offset & IP_OFFMASK));
  571         if (offset & IP_RF)
  572                 (*pr)("IP: Flag 0x%04x (reserved)\n", IP_RF);
  573         if (offset & IP_EF)
  574                 (*pr)("IP: Flag 0x%04x (evil flag)\n", IP_EF);
  575         if (offset & IP_DF)
  576                 (*pr)("IP: Flag 0x%04x (don't fragment)\n", IP_DF);
  577         if (offset & IP_MF)
  578                 (*pr)("IP: Flag 0x%04x (more fragment)\n", IP_MF);
  579         (*pr)("IP: TTL = %u\n", ip.ip_ttl);
  580         (*pr)("IP: protocol = %u(%s)\n", ip.ip_p, str_ipproto(ip.ip_p));
  581         (*pr)("IP: checksum = 0x%04x\n", ntohs(ip.ip_sum));
  582         (*pr)("IP: Src = %s\n", str_ipaddr(&ip.ip_src));
  583         (*pr)("IP: Dst = %s\n", str_ipaddr(&ip.ip_dst));
  584 
  585         switch (ip.ip_p) {
  586         case IPPROTO_ICMP:
  587                 return m_examine_icmp(m, off, modif, pr);
  588                 break;
  589         case IPPROTO_TCP:
  590                 return m_examine_tcp(m, off, modif, pr);
  591                 break;
  592         case IPPROTO_UDP:
  593                 return m_examine_udp(m, off, modif, pr);
  594                 break;
  595         default:
  596                 break;
  597         }
  598 
  599         return m_examine_hex(m, off, modif, pr);
  600 }
  601 
  602 void
  603 m_examine_icmp(const struct mbuf *m, int off, const char *modif,
  604     void (*pr)(const char *, ...))
  605 {
  606         unsigned int pktlen;
  607         struct icmp icmphdr;
  608 
  609         pktlen = m_peek_len(m, modif) - off;
  610         if (pktlen < sizeof(icmphdr)) {
  611                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  612                     pktlen, sizeof(icmphdr));
  613                 return m_examine_hex(m, off, modif, pr);
  614         }
  615 
  616         if (m_peek_data(m, off, sizeof(icmphdr), (void *)(&icmphdr)) < 0) {
  617                 (*pr)("%s: cannot read header\n", __func__);
  618                 return m_examine_hex(m, off, modif, pr);
  619         }
  620         off += sizeof(icmphdr);
  621 
  622         (*pr)("ICMP: Type = %u(", icmphdr.icmp_type);
  623         switch (icmphdr.icmp_type) {
  624         case ICMP_ECHOREPLY:
  625                 (*pr)("Echo Reply)\n");
  626                 break;
  627         case ICMP_UNREACH:
  628                 (*pr)("Destination Unreachable)\n");
  629                 break;
  630         case ICMP_SOURCEQUENCH:
  631                 (*pr)("Source Quench)\n");
  632                 break;
  633         case ICMP_REDIRECT:
  634                 (*pr)("Redirect)\n");
  635                 break;
  636         case ICMP_TIMXCEED:
  637                 (*pr)("Time Exceeded)\n");
  638                 break;
  639         default:
  640                 (*pr)("unknown)\n");
  641                 break;
  642         }
  643         (*pr)("ICMP: Code = %d\n", icmphdr.icmp_code);
  644 
  645         return m_examine_hex(m, off, modif, pr);
  646 }
  647 
  648 void
  649 m_examine_ip6(const struct mbuf *m, int off, const char *modif,
  650     void (*pr)(const char *, ...))
  651 {
  652         unsigned int pktlen;
  653         struct ip6_hdr ip6;
  654         struct ip6_hbh hbh;
  655         int hbhlen;
  656         uint32_t flow;
  657         uint8_t vfc;
  658         uint8_t nxt;
  659 
  660         pktlen = m_peek_len(m, modif) - off;
  661         if (pktlen < sizeof(ip6)) {
  662                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  663                     pktlen, sizeof(ip6));
  664                 return m_examine_hex(m, off, modif, pr);
  665         }
  666 
  667         if (m_peek_data(m, off, sizeof(ip6), (void *)(&ip6)) < 0) {
  668                 (*pr)("%s: cannot read header\n", __func__);
  669                 return m_examine_hex(m, off, modif, pr);
  670         }
  671         off += sizeof(ip6);
  672 
  673         vfc = ip6.ip6_vfc;
  674         (*pr)("IPv6: Version = %u\n", (vfc & IPV6_VERSION_MASK) >> 4);
  675         flow = ntohl(ip6.ip6_flow);
  676         (*pr)("IPv6: Flow INFO = 0x%07x\n", flow & IPV6_FLOWINFO_MASK);
  677         (*pr)("IPv6: Payload Length = %u\n", ntohs(ip6.ip6_plen));
  678         nxt = ip6.ip6_nxt;
  679         (*pr)("IPv6: Next Header = %u(%s)\n", nxt, str_ipproto(nxt));
  680         (*pr)("IPv6: Hop Limit = %u\n", ip6.ip6_hlim);
  681         (*pr)("IPv6: Src = %s\n", str_ip6addr(&ip6.ip6_src));
  682         (*pr)("IPv6: Dst = %s\n", str_ip6addr(&ip6.ip6_dst));
  683 
  684         /* Strip Hop-by-Hop options */
  685         if (nxt == IPPROTO_HOPOPTS) {
  686                 if (m_peek_data(m, off, sizeof(hbh), (void *)(&hbh)) < 0) {
  687                         (*pr)("Cannot read option\n");
  688                         return m_examine_hex(m, off, modif, pr);
  689                 }
  690                 hbhlen = (hbh.ip6h_len + 1) << 3;
  691                 nxt = hbh.ip6h_nxt;
  692                 off += hbhlen;
  693 
  694                 (*pr)("IPv6: Stripped Hop-by-Hop\n");
  695                 (*pr)("IPv6: Next Header = %u(%s)\n", nxt, str_ipproto(nxt));
  696         }
  697 
  698         switch (nxt) {
  699         case IPPROTO_IPV6_ICMP:
  700                 return m_examine_icmp6(m, off, modif, pr);
  701                 break;
  702         case IPPROTO_TCP:
  703                 return m_examine_tcp(m, off, modif, pr);
  704                 break;
  705         case IPPROTO_UDP:
  706                 return m_examine_udp(m, off, modif, pr);
  707                 break;
  708         default:
  709                 break;
  710         }
  711 
  712         return m_examine_hex(m, off, modif, pr);
  713 }
  714 
  715 void
  716 m_examine_icmp6(const struct mbuf *m, int off, const char *modif,
  717     void (*pr)(const char *, ...))
  718 {
  719         unsigned int pktlen;
  720         struct icmp6_hdr icmp6;
  721 
  722         pktlen = m_peek_len(m, modif) - off;
  723         if (pktlen < sizeof(icmp6)) {
  724                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  725                     pktlen, sizeof(icmp6));
  726                 return m_examine_hex(m, off, modif, pr);
  727         }
  728 
  729         if (m_peek_data(m, off, sizeof(icmp6), (void *)(&icmp6)) < 0) {
  730                 (*pr)("%s: cannot read header\n", __func__);
  731                 return m_examine_hex(m, off, modif, pr);
  732         }
  733         off += sizeof(icmp6);
  734 
  735         (*pr)("ICMP6: Type = %u(", icmp6.icmp6_type);
  736         switch (icmp6.icmp6_type) {
  737         case ICMP6_DST_UNREACH:
  738                 (*pr)("Destination Unreachable)\n");
  739                 break;
  740         case ICMP6_PACKET_TOO_BIG:
  741                 (*pr)("Packet Too Big)\n");
  742                 break;
  743         case ICMP6_TIME_EXCEEDED:
  744                 (*pr)("Time Exceeded)\n");
  745                 break;
  746         case ICMP6_PARAM_PROB:
  747                 (*pr)("Parameter Problem)\n");
  748                 break;
  749         case ICMP6_ECHO_REQUEST:
  750                 (*pr)("Echo Request)\n");
  751                 break;
  752         case ICMP6_ECHO_REPLY:
  753                 (*pr)("Echo Reply)\n");
  754                 break;
  755 
  756         case MLD_LISTENER_QUERY:
  757                 (*pr)("MLD Listener Query)\n");
  758                 break;
  759         case MLD_LISTENER_REPORT:
  760                 (*pr)("MLD Listener Report)\n");
  761                 break;
  762         case MLD_LISTENER_DONE:
  763                 (*pr)("MLD Listener Done)\n");
  764                 break;
  765 
  766         case ND_ROUTER_SOLICIT:
  767                 (*pr)("Router Solicitation)\n");
  768                 break;
  769         case ND_ROUTER_ADVERT:
  770                 (*pr)("Router Advertizement)\n");
  771                 break;
  772         case ND_NEIGHBOR_SOLICIT:
  773                 (*pr)("Neighbor Solicitation)\n");
  774                 break;
  775         case ND_NEIGHBOR_ADVERT:
  776                 (*pr)("Neighbor Advertizement)\n");
  777                 break;
  778         case ND_REDIRECT:
  779                 (*pr)("Redirect)\n");
  780                 break;
  781 
  782         default:
  783                 (*pr)("unknown)\n");
  784                 break;
  785         }
  786         (*pr)("ICMP6: Code = %u\n", icmp6.icmp6_code);
  787 
  788         return m_examine_hex(m, off, modif, pr);
  789 }
  790 
  791 void
  792 m_examine_tcp(const struct mbuf *m, int off, const char *modif,
  793     void (*pr)(const char *, ...))
  794 {
  795         unsigned int pktlen;
  796         struct tcphdr tcp;
  797 
  798         pktlen = m_peek_len(m, modif) - off;
  799         if (pktlen < sizeof(tcp)) {
  800                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  801                     pktlen, sizeof(tcp));
  802                 return m_examine_hex(m, off, modif, pr);
  803         }
  804 
  805         if (m_peek_data(m, off, sizeof(tcp), (void *)(&tcp)) < 0) {
  806                 (*pr)("%s: cannot read header\n", __func__);
  807                 return m_examine_hex(m, off, modif, pr);
  808         }
  809         off += sizeof(tcp);
  810 
  811         (*pr)("TCP: Src = %u\n", ntohs(tcp.th_sport));
  812         (*pr)("TCP: Dst = %u\n", ntohs(tcp.th_dport));
  813         (*pr)("TCP: Seq. = %u\n", ntohl(tcp.th_seq));
  814         (*pr)("TCP: Ack. = %u\n", ntohl(tcp.th_ack));
  815         (*pr)("TCP: Header Length = %u\n", tcp.th_off << 2);
  816         if (tcp.th_flags) {
  817                 (*pr)("TCP: Flags 0x%02x : ", tcp.th_flags);
  818                 if (tcp.th_flags & TH_FIN)
  819                         (*pr)("FIN ");
  820                 if (tcp.th_flags & TH_SYN)
  821                         (*pr)("SYN ");
  822                 if (tcp.th_flags & TH_RST)
  823                         (*pr)("RST ");
  824                 if (tcp.th_flags & TH_PUSH)
  825                         (*pr)("PUSH ");
  826                 if (tcp.th_flags & TH_URG)
  827                         (*pr)("URG ");
  828                 if (tcp.th_flags & TH_ECE)
  829                         (*pr)("ECE ");
  830                 if (tcp.th_flags & TH_CWR)
  831                         (*pr)("CWR ");
  832                 (*pr)("\n");
  833         }
  834         (*pr)("TCP: Windows Size = %u\n", ntohs(tcp.th_win));
  835         (*pr)("TCP: checksum = 0x%04x\n", ntohs(tcp.th_sum));
  836         (*pr)("TCP: Urgent Pointer = %u\n", ntohs(tcp.th_urp));
  837 
  838         int len;
  839         len = (tcp.th_off << 2) - sizeof(struct tcphdr);
  840         if (len > 0) {
  841                 uint8_t *bufp, *op, opt, optlen;
  842 
  843                 bufp = malloc(len, M_TEMP, M_DONTWAIT);
  844                 if ((bufp == NULL) || (m_peek_data(m, off, len, bufp) < 0)) {
  845                         (*pr)("%s: cannot read TCP option\n", __func__);
  846                         if (bufp != NULL)
  847                                 free(bufp, M_TEMP);
  848                         return m_examine_hex(m, off, modif, pr);
  849                 }
  850                 off += len;
  851                 op = bufp;
  852 
  853                 while (len > 0) {
  854                         opt = op[0];
  855                         if (opt == TCPOPT_EOL)
  856                                 break;
  857                         if (opt == TCPOPT_NOP) {
  858                                 (*pr)("TCP: OPTION: NOP\n");
  859                                 op++;
  860                                 len--;
  861                                 continue;
  862                         }
  863                         if (opt == TCPOPT_PAD) {
  864                                 (*pr)("TCP: OPTION: PAD\n");
  865                                 op++;
  866                                 len--;
  867                                 continue;
  868                         }
  869                         optlen = op[1];
  870                         if (optlen == 0)
  871                                 break;
  872 
  873                         if (opt == TCPOPT_MAXSEG && optlen == TCPOLEN_MAXSEG) {
  874                                 uint16_t mss;
  875 
  876                                 bcopy(op + 2, &mss, sizeof(mss));
  877                                 (*pr)("TCP: OPTION: MSS = %d\n",
  878                                     ntohs(mss));
  879 
  880                                 op += optlen;
  881                                 len -= optlen;
  882                                 continue;
  883                         } else if (opt == TCPOPT_WINDOW
  884                             && optlen == TCPOLEN_WINDOW) {
  885                                 (*pr)("TCP: OPTION: wscale = %d\n", op[2]);
  886                                 op += optlen;
  887                                 len -= optlen;
  888                                 continue;
  889                         } else if (opt == TCPOPT_SACK_PERMITTED
  890                             && optlen == TCPOLEN_SACK_PERMITTED) {
  891                                 (*pr)("TCP: OPTION: SACK OK\n");
  892                                 op += optlen;
  893                                 len -= optlen;
  894                                 continue;
  895                         } else if (opt == TCPOPT_TIMESTAMP
  896                             && optlen == TCPOLEN_TIMESTAMP) {
  897                                 uint32_t ts_val, ts_ecr;
  898 
  899                                 memcpy(&ts_val, op + 2, sizeof(ts_val));
  900                                 memcpy(&ts_ecr, op + 6, sizeof(ts_ecr));
  901                                 (*pr)("TCP: OPTION: TIMESTAMP = %u, "
  902                                     "ECR = %u\n",
  903                                     ntohl(ts_val), ntohl(ts_ecr));
  904                                 op += optlen;
  905                                 len -= optlen;
  906                                 continue;
  907                         } else {
  908                                 (*pr)("TCP: OPTION: unknown (%d, len = %d)\n",
  909                                     opt, optlen);
  910                                 op += optlen;
  911                                 len -= optlen;
  912                                 continue;
  913                         }
  914                 }
  915                 free(bufp, M_TEMP);
  916         }
  917 
  918         if (off < pktlen)
  919                 m_examine_hex(m, off, modif, pr);
  920 
  921         return;
  922 }
  923 
  924 void
  925 m_examine_udp(const struct mbuf *m, int off, const char *modif,
  926     void (*pr)(const char *, ...))
  927 {
  928         unsigned int pktlen;
  929         struct udphdr udp;
  930 
  931         pktlen = m_peek_len(m, modif) - off;
  932         if (pktlen < sizeof(udp)) {
  933                 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__,
  934                     pktlen, sizeof(udp));
  935                 return m_examine_hex(m, off, modif, pr);
  936         }
  937 
  938         if (m_peek_data(m, off, sizeof(udp), (void *)(&udp)) < 0) {
  939                 (*pr)("%s: cannot read header\n", __func__);
  940                 return m_examine_hex(m, off, modif, pr);
  941         }
  942         off += sizeof(udp);
  943 
  944         (*pr)("UDP: Src = %u\n", ntohs(udp.uh_sport));
  945         (*pr)("UDP: Dst = %u\n", ntohs(udp.uh_dport));
  946         (*pr)("UDP: Length = %u\n", ntohs(udp.uh_ulen));
  947 
  948         return m_examine_hex(m, off, modif, pr);
  949 }
  950 
  951 void
  952 m_examine_hex(const struct mbuf *m, int off, const char *modif,
  953     void (*pr)(const char *, ...))
  954 {
  955         unsigned int pktlen;
  956         int newline = 0;
  957         uint8_t v;
  958 
  959         pktlen = m_peek_len(m, modif) - off;
  960         if (pktlen > EXAMINE_HEX_LIMIT)
  961                 pktlen = EXAMINE_HEX_LIMIT;
  962 
  963         if (pktlen == 0)
  964                 return;
  965 
  966         (*pr)("offset %04d: ", off);
  967         while (pktlen > 0) {
  968                 if (m_peek_data(m, off, sizeof(v), (void *)(&v)) < 0)
  969                         break;
  970                 pktlen --;
  971                 off++;
  972                 newline++;
  973 
  974                 (*pr)("%02x", v);
  975                 if (pktlen == 0)
  976                         break;
  977 
  978                 if ((newline % EXAMINE_HEX_COL) == 0) {
  979                         (*pr)("\n");
  980                         (*pr)("offset %04d: ", off);
  981                 } else
  982                         (*pr)(" ");
  983         }
  984         (*pr)("\n");
  985 }
  986 
  987 void
  988 m_examine(const struct mbuf *m, int af, const char *modif,
  989     void (*pr)(const char *, ...))
  990 {
  991         if (m == NULL)
  992                 return;
  993 
  994         if (pr == NULL)
  995                 return;
  996 
  997         switch (af) {
  998         case AF_UNSPEC:
  999                 return m_examine_hex(m, 0, modif, pr);
 1000                 break;
 1001         case AF_ETHER:
 1002                 return m_examine_ether(m, 0, modif, pr);
 1003                 break;
 1004         case AF_ARP:
 1005                 return m_examine_arp(m, 0, modif, pr);
 1006                 break;
 1007         case AF_INET:
 1008                 return m_examine_ip(m, 0, modif, pr);
 1009                 break;
 1010         case AF_INET6:
 1011                 return m_examine_ip6(m, 0, modif, pr);
 1012                 break;
 1013         default:
 1014                 (*pr)("No parser for AF %d\n", af);
 1015                 return m_examine_hex(m, 0, modif, pr);
 1016                 break;
 1017         }
 1018 
 1019         /* not reached */
 1020         return;
 1021 }

Cache object: 0a74f28dcfdf5a1f368578e6506eac83


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.