LCOV - code coverage report
Current view: top level - server - process_packet.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 52 56 92.9 %
Date: 2016-06-07 Functions: 1 1 100.0 %
Branches: 23 40 57.5 %

           Branch data     Line data    Source code
       1                 :            : /**
       2                 :            :  * \file server/process_packet.c
       3                 :            :  *
       4                 :            :  * \brief Packet parser/decoder for fwknopd server.
       5                 :            :  *
       6                 :            :  *          Takes the raw packet
       7                 :            :  *          data from libpcap and parses/extracts the packet data payload,
       8                 :            :  *          then creates an FKO context with that data.  If the context
       9                 :            :  *          creation is successful, it is queued for processing.
      10                 :            :  */
      11                 :            : 
      12                 :            : /*  Fwknop is developed primarily by the people listed in the file 'AUTHORS'.
      13                 :            :  *  Copyright (C) 2009-2015 fwknop developers and contributors. For a full
      14                 :            :  *  list of contributors, see the file 'CREDITS'.
      15                 :            :  *
      16                 :            :  *  License (GNU General Public License):
      17                 :            :  *
      18                 :            :  *  This program is free software; you can redistribute it and/or
      19                 :            :  *  modify it under the terms of the GNU General Public License
      20                 :            :  *  as published by the Free Software Foundation; either version 2
      21                 :            :  *  of the License, or (at your option) any later version.
      22                 :            :  *
      23                 :            :  *  This program is distributed in the hope that it will be useful,
      24                 :            :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      25                 :            :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      26                 :            :  *  GNU General Public License for more details.
      27                 :            :  *
      28                 :            :  *  You should have received a copy of the GNU General Public License
      29                 :            :  *  along with this program; if not, write to the Free Software
      30                 :            :  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
      31                 :            :  *  USA
      32                 :            :  *
      33                 :            :  *****************************************************************************
      34                 :            : */
      35                 :            : 
      36                 :            : #include "fwknopd_common.h"
      37                 :            : #include "netinet_common.h"
      38                 :            : #include "process_packet.h"
      39                 :            : #include "incoming_spa.h"
      40                 :            : #include "utils.h"
      41                 :            : #include "log_msg.h"
      42                 :            : 
      43                 :            : 
      44                 :            : void
      45                 :      18791 : process_packet(PROCESS_PKT_ARGS_TYPE *args, PACKET_HEADER_META,
      46                 :            :                const unsigned char *packet)
      47                 :            : {
      48                 :            :     struct ether_header *eth_p;
      49                 :            :     struct iphdr        *iph_p;
      50                 :            :     struct tcphdr       *tcph_p;
      51                 :            :     struct udphdr       *udph_p;
      52                 :            :     struct icmphdr      *icmph_p;
      53                 :            : 
      54                 :            :     unsigned char       *pkt_data;
      55                 :            :     unsigned short      pkt_data_len;
      56                 :            :     unsigned char       *pkt_end;
      57                 :            :     unsigned char       *fr_end;
      58                 :            : 
      59                 :            :     unsigned int        ip_hdr_words;
      60                 :            : 
      61                 :            :     unsigned char       proto;
      62                 :            :     unsigned int        src_ip;
      63                 :            :     unsigned int        dst_ip;
      64                 :            : 
      65                 :      18791 :     unsigned short      src_port = 0;
      66                 :      18791 :     unsigned short      dst_port = 0;
      67                 :            : 
      68                 :            :     unsigned short      eth_type;
      69                 :            : 
      70                 :      18791 :     fko_srv_options_t   *opts = (fko_srv_options_t *)args;
      71                 :            : 
      72                 :      18791 :     int                 offset = opts->data_link_offset;
      73                 :            : 
      74                 :            : #if USE_LIBPCAP
      75                 :      18791 :     unsigned short      pkt_len = packet_header->len;
      76                 :            : 
      77                 :            :     /* Gotta have a complete ethernet header.
      78                 :            :     */
      79         [ +  - ]:      18791 :     if (packet_header->caplen < ETHER_HDR_LEN)
      80                 :            :         return;
      81                 :            : 
      82                 :            :     /* Determine packet end.
      83                 :            :     */
      84                 :      18791 :     fr_end = (unsigned char *) packet + packet_header->caplen;
      85                 :            : #else
      86                 :            :     /* This is coming from NFQ and we get the packet lentgh as an arg.
      87                 :            :     */
      88                 :            :     if (pkt_len < ETHER_HDR_LEN)
      89                 :            :         return;
      90                 :            :     fr_end = (unsigned char *) packet + pkt_len;
      91                 :            : #endif
      92                 :            : 
      93                 :            :     /* This is a hack to determine if we are using the linux cooked
      94                 :            :      * interface.  We base it on the offset being 16 which is the
      95                 :            :      * value it would be if the datalink is DLT_LINUX_SLL.  I don't
      96                 :            :      * know if this is the correct way to do this, but it seems to work.
      97                 :            :     */
      98                 :      18791 :     unsigned char       assume_cooked = (offset == 16 ? 1 : 0);
      99                 :            : 
     100                 :            :     /* The ethernet header.
     101                 :            :     */
     102                 :      18791 :     eth_p = (struct ether_header*) packet;
     103                 :            : 
     104         [ -  + ]:      18791 :     eth_type = ntohs(*((unsigned short*)&eth_p->ether_type));
     105                 :            : 
     106         [ -  + ]:      18791 :     if(eth_type == 0x8100) /* 802.1q encapsulated */
     107                 :            :     {
     108                 :          0 :         offset += 4;
     109         [ #  # ]:          0 :         eth_type = ntohs(*(((unsigned short*)&eth_p->ether_type)+2));
     110                 :            :     }
     111                 :            : 
     112                 :            :     /* When using libpcap, pkthdr->len for 802.3 frames include CRC_LEN,
     113                 :            :      * but Ethenet_II frames do not.
     114                 :            :     */
     115         [ +  - ]:      18791 :     if (eth_type > 1500 || assume_cooked == 1)
     116                 :            :     {
     117                 :      18791 :         pkt_len += ETHER_CRC_LEN;
     118                 :            : 
     119         [ -  + ]:      18791 :         if(eth_type == 0xAAAA)      /* 802.2 SNAP */
     120                 :          0 :             offset += 5;
     121                 :            :     }
     122                 :            :     else /* 802.3 Frame */
     123                 :          0 :         offset += 3;
     124                 :            : 
     125                 :            :     /* Make sure the packet length is still valid.
     126                 :            :     */
     127         [ +  + ]:      18791 :     if (! ETHER_IS_VALID_LEN(pkt_len) )
     128                 :            :         return;
     129                 :            : 
     130                 :            :     /* Pull the IP header.
     131                 :            :     */
     132                 :      18782 :     iph_p = (struct iphdr*)(packet + offset);
     133                 :            : 
     134                 :            :     /* If IP header is past calculated packet end, bail.
     135                 :            :     */
     136         [ +  - ]:      18782 :     if ((unsigned char*)(iph_p + 1) > fr_end)
     137                 :            :         return;
     138                 :            : 
     139                 :            :     /* ip_hdr_words is the number of 32 bit words in the IP header. After
     140                 :            :      * masking of the IPV4 version bits, the number *must* be at least
     141                 :            :      * 5, even without options.
     142                 :            :     */
     143                 :      18782 :     ip_hdr_words = iph_p->ihl & IPV4_VER_MASK;
     144                 :            : 
     145         [ +  - ]:      18782 :     if (ip_hdr_words < MIN_IPV4_WORDS)
     146                 :            :         return;
     147                 :            : 
     148                 :            :     /* Make sure to calculate the packet end based on the length in the
     149                 :            :      * IP header. This allows additional bytes that may be added to the
     150                 :            :      * frame (such as a 4-byte Ethernet Frame Check Sequence) to not
     151                 :            :      * interfere with SPA operations.
     152                 :            :     */
     153         [ -  + ]:      18782 :     pkt_end = ((unsigned char*)iph_p)+ntohs(iph_p->tot_len);
     154         [ +  - ]:      18782 :     if(pkt_end > fr_end)
     155                 :            :         return;
     156                 :            : 
     157                 :            :     /* Now, find the packet data payload (depending on IPPROTO).
     158                 :            :     */
     159                 :      18782 :     src_ip = iph_p->saddr;
     160                 :      18782 :     dst_ip = iph_p->daddr;
     161                 :            : 
     162                 :      18782 :     proto = iph_p->protocol;
     163                 :            : 
     164         [ +  + ]:      18782 :     if (proto == IPPROTO_TCP)
     165                 :            :     {
     166                 :            :         /* Process TCP packet
     167                 :            :         */
     168                 :         32 :         tcph_p = (struct tcphdr*)((unsigned char*)iph_p + (ip_hdr_words << 2));
     169                 :            : 
     170         [ -  + ]:         32 :         src_port = ntohs(tcph_p->source);
     171         [ -  + ]:         32 :         dst_port = ntohs(tcph_p->dest);
     172                 :            : 
     173                 :         32 :         pkt_data = ((unsigned char*)(tcph_p+1))+((tcph_p->doff)<<2)-sizeof(struct tcphdr);
     174                 :            : 
     175                 :         32 :         pkt_data_len = (pkt_end-(unsigned char*)iph_p)-(pkt_data-(unsigned char*)iph_p);
     176                 :            :     }
     177         [ +  + ]:      18750 :     else if (proto == IPPROTO_UDP)
     178                 :            :     {
     179                 :            :         /* Process UDP packet
     180                 :            :         */
     181                 :      18748 :         udph_p = (struct udphdr*)((unsigned char*)iph_p + (ip_hdr_words << 2));
     182                 :            : 
     183         [ -  + ]:      18748 :         src_port = ntohs(udph_p->source);
     184         [ -  + ]:      18748 :         dst_port = ntohs(udph_p->dest);
     185                 :            : 
     186                 :      18748 :         pkt_data = ((unsigned char*)(udph_p + 1));
     187                 :      18748 :         pkt_data_len = (pkt_end-(unsigned char*)iph_p)-(pkt_data-(unsigned char*)iph_p);
     188                 :            :     }
     189         [ +  - ]:          2 :     else if (proto == IPPROTO_ICMP)
     190                 :            :     {
     191                 :            :         /* Process ICMP packet
     192                 :            :         */
     193                 :          2 :         icmph_p = (struct icmphdr*)((unsigned char*)iph_p + (ip_hdr_words << 2));
     194                 :            : 
     195                 :          2 :         pkt_data = ((unsigned char*)(icmph_p + 1));
     196                 :          2 :         pkt_data_len = (pkt_end-(unsigned char*)iph_p)-(pkt_data-(unsigned char*)iph_p);
     197                 :            :     }
     198                 :            : 
     199                 :            :     else
     200                 :            :         return;
     201                 :            : 
     202                 :            :     /*
     203                 :            :      * Now we have data. For now, we are not checking IP or port values. We
     204                 :            :      * are relying on the pcap filter. This may change so we do retain the IP
     205                 :            :      * addresses and ports just in case. We just go ahead and queue the
     206                 :            :      * data.
     207                 :            :     */
     208                 :            : 
     209                 :            :     /* Expect the data to be at least the minimum required size.  This check
     210                 :            :      * will weed out a lot of things like small TCP ACK's if the user has a
     211                 :            :      * permissive pcap filter
     212                 :            :     */
     213         [ +  + ]:      18782 :     if(pkt_data_len < MIN_SPA_DATA_SIZE)
     214                 :            :         return;
     215                 :            : 
     216                 :            :     /* Expect the data to not be too large
     217                 :            :     */
     218         [ +  - ]:      18753 :     if(pkt_data_len > MAX_SPA_PACKET_LEN)
     219                 :            :         return;
     220                 :            : 
     221                 :            :     /* Copy the packet for SPA processing
     222                 :            :     */
     223                 :      18753 :     strlcpy((char *)opts->spa_pkt.packet_data, (char *)pkt_data, pkt_data_len+1);
     224                 :      18753 :     opts->spa_pkt.packet_data_len = pkt_data_len;
     225                 :      18753 :     opts->spa_pkt.packet_proto    = proto;
     226                 :      18753 :     opts->spa_pkt.packet_src_ip   = src_ip;
     227                 :      18753 :     opts->spa_pkt.packet_dst_ip   = dst_ip;
     228                 :      18753 :     opts->spa_pkt.packet_src_port = src_port;
     229                 :      18753 :     opts->spa_pkt.packet_dst_port = dst_port;
     230                 :            : 
     231                 :      18753 :     incoming_spa(opts);
     232                 :            : 
     233                 :      18753 :     return;
     234                 :            : }
     235                 :            : 
     236                 :            : 
     237                 :            : /***EOF***/

Generated by: LCOV version 1.10