"Fossies" - the Fresh Open Source Software Archive

Member "ettercap-0.8.3.1/src/protocols/ec_ip6.c" (1 Aug 2020, 8855 Bytes) of package /linux/privat/ettercap-0.8.3.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ec_ip6.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.8.3_vs_0.8.3.1.

    1 /*
    2     ettercap -- IPv6 decoder module
    3 
    4     Copyright (C) ALoR & NaGA
    5 
    6     This program is free software; you can redistribute it and/or modify
    7     it under the terms of the GNU General Public License as published by
    8     the Free Software Foundation; either version 2 of the License, or
    9     (at your option) any later version.
   10 
   11     This program is distributed in the hope that it will be useful,
   12     but WITHOUT ANY WARRANTY; without even the implied warranty of
   13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14     GNU General Public License for more details.
   15 
   16     You should have received a copy of the GNU General Public License
   17     along with this program; if not, write to the Free Software
   18     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   19 
   20 */
   21 
   22 #include <ec.h>
   23 #include <ec_decode.h>
   24 #include <ec_inject.h>
   25 #include <ec_inet.h>
   26 #include <ec_session.h>
   27 //#include <ec_fingerprint.h>
   28 
   29 #define IP6_HDR_LEN 40
   30 
   31 /* globals */
   32 
   33 struct ip6_header {
   34 #ifndef WORDS_BIGENDIAN
   35    u_int8   version:4;
   36    u_int8   priority:4;
   37 #else 
   38    u_int8   priority:4;
   39    u_int8   version:4;
   40 #endif
   41    u_int8   flow_lbl[3];
   42    u_int16  payload_len;
   43    u_int8   next_hdr;
   44    u_int8   hop_limit;
   45 
   46    u_int8   saddr[IP6_ADDR_LEN];
   47    u_int8   daddr[IP6_ADDR_LEN];
   48 };
   49 
   50 struct ip6_ext_header {
   51     u_int8 next_hdr;
   52     u_int8 hdr_len;
   53 
   54     /* Here must be options */
   55 };
   56 
   57 struct ip6_ident {
   58    u_int32 magic;
   59 #define IP6_MAGIC    0x0306e77e
   60    u_int8 flow_lbl[3];
   61    struct ip_addr L3_src;
   62 };
   63 
   64 struct ip6_data {
   65    u_int8 priority :4;
   66 };
   67 
   68 /* protos */
   69 
   70 void ip6_init(void);
   71 FUNC_DECODER(decode_ip6);
   72 FUNC_DECODER(decode_ip6_ext);
   73 FUNC_INJECTOR(inject_ip6);
   74 static size_t ip6_create_ident(void **i, struct packet_object *po);
   75 static int ip6_match(void *ident_s, void *ident_c);
   76 static void ip6_create_session(struct ec_session **s, struct packet_object *po);
   77 
   78 /*******************************************/
   79 
   80 /*
   81  * this function is the initializer.
   82  * it adds the entry in the table of registered decoder
   83  */
   84 
   85 void __init ip6_init(void)
   86 {
   87    add_decoder(NET_LAYER, LL_TYPE_IP6, decode_ip6);
   88    add_decoder(PROTO_LAYER, NL_TYPE_IP6, decode_ip6);
   89    add_decoder(NET6_LAYER, LO6_TYPE_HBH, decode_ip6_ext);
   90    add_decoder(NET6_LAYER, LO6_TYPE_RT, decode_ip6_ext);
   91    add_decoder(NET6_LAYER, LO6_TYPE_DST, decode_ip6_ext);
   92 
   93    add_injector(CHAIN_LINKED, IP6_MAGIC, inject_ip6);
   94 }
   95 
   96 
   97 FUNC_DECODER(decode_ip6)
   98 {
   99    FUNC_DECODER_PTR(next_decoder);
  100    struct ip6_header *ip6;
  101    struct ec_session *s;
  102    void *ident;
  103 
  104    ip6 = (struct ip6_header *)DECODE_DATA;
  105   
  106    if (ip6->payload_len == 0) {
  107       DEBUG_MSG("IPv6 jumbogram, Hop-By-Hop header should follow");
  108    }
  109    DECODED_LEN = IP6_HDR_LEN;
  110 
  111    /* IP addresses */
  112    ip_addr_init(&PACKET->L3.src, AF_INET6, (u_char *)&ip6->saddr);
  113    ip_addr_init(&PACKET->L3.dst, AF_INET6, (u_char *)&ip6->daddr);
  114    
  115    /* this is needed at upper layer to calculate the tcp payload size */
  116    PACKET->L3.payload_len = ntohs(ip6->payload_len);
  117       
  118    /* other relevant infos */
  119    PACKET->L3.header = (u_char *)DECODE_DATA;
  120    PACKET->L3.len = DECODED_LEN;
  121 
  122    PACKET->L3.proto = htons(LL_TYPE_IP6);
  123    PACKET->L3.ttl = ip6->hop_limit;
  124 
  125    if(PACKET->fwd_packet == NULL) {
  126       EXECUTE(EC_GBL_SNIFF->check_forwarded, PACKET);
  127       /* if it is already forwarded */
  128       if(PACKET->flags & PO_FORWARDED)
  129          return NULL;
  130       EXECUTE(EC_GBL_SNIFF->set_forwardable, PACKET);
  131       PACKET->fwd_packet = (u_char *)DECODE_DATA;
  132       PACKET->fwd_len = PACKET->L3.payload_len + DECODED_LEN;
  133    }
  134 
  135    /* calculate if the dest is local or not */
  136    switch (ip_addr_is_local(&PACKET->L3.src, NULL)) {
  137       case E_SUCCESS:
  138          PACKET->PASSIVE.flags &= ~(FP_HOST_NONLOCAL);
  139          PACKET->PASSIVE.flags |= FP_HOST_LOCAL;
  140          break;
  141       case -E_NOTFOUND:
  142          PACKET->PASSIVE.flags &= ~FP_HOST_LOCAL;
  143          PACKET->PASSIVE.flags |= FP_HOST_NONLOCAL;
  144          break;
  145       case -E_INVALID:
  146          PACKET->PASSIVE.flags = FP_UNKNOWN;
  147          break;
  148    }
  149    
  150    next_decoder = get_decoder(NET6_LAYER, ip6->next_hdr);
  151    if(next_decoder == NULL) {
  152       PACKET->L3.options = NULL;
  153       PACKET->L3.optlen = 0;
  154       next_decoder = get_decoder(PROTO_LAYER, ip6->next_hdr);
  155    } else {
  156       PACKET->L3.options = (u_char *)&ip6[1];
  157    }
  158       
  159    /* HOOK POINT: HOOK_PACKET_IP6 */
  160    hook_point(HOOK_PACKET_IP6, po);
  161 
  162    if(!EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read) {
  163       ip6_create_ident(&ident, PACKET);
  164 
  165       if(session_get(&s, ident, sizeof(struct ip6_ident)) == -E_NOTFOUND) {
  166          ip6_create_session(&s, PACKET);
  167          session_put(s);
  168       }
  169       SAFE_FREE(ident);
  170 
  171       SESSION_PASSTHRU(s, PACKET);
  172    }
  173    
  174    /* passing the packet to options or upper-layer decoder */
  175    EXECUTE_DECODER(next_decoder);
  176    
  177    /*
  178     * External L3 header sets itself 
  179     * as the packet to be forwarded.
  180     */
  181    /* XXX - recheck this */
  182    if(!EC_GBL_OPTIONS->unoffensive && !EC_GBL_OPTIONS->read && (PACKET->flags & PO_FORWARDABLE)) {
  183       if(PACKET->flags & PO_MODIFIED) {
  184          ORDER_ADD_SHORT(ip6->payload_len, PACKET->DATA.delta);
  185 
  186          /*
  187           * In case some upper level encapsulated ip6 decoder
  188           * modified it ... (required for ip6 in ip6 encapsulation)
  189           */
  190          PACKET->L3.header = (u_char*)ip6;
  191          PACKET->L3.len = IP6_HDR_LEN;
  192          PACKET->L3.payload_len = ntohs(ip6->payload_len);
  193 
  194          PACKET->fwd_len = PACKET->L3.payload_len + PACKET->L3.len;
  195       }
  196    }
  197    
  198    return NULL;
  199 }
  200 
  201 /* XXX - dirty stuff just to make things work.
  202  * Rewrite it to handle extension headers (if needed).
  203  */
  204 FUNC_DECODER(decode_ip6_ext)
  205 {
  206    FUNC_DECODER_PTR(next_decoder);
  207    struct ip6_ext_header *ext_hdr;
  208 
  209    ext_hdr = (struct ip6_ext_header *)DECODE_DATA;
  210    PACKET->L3.optlen += ext_hdr->hdr_len + 1;
  211    DECODED_LEN = ext_hdr->hdr_len + 1;
  212 
  213    next_decoder = get_decoder(NET6_LAYER, ext_hdr->next_hdr);
  214    if(next_decoder == NULL) {
  215       next_decoder = get_decoder(PROTO_LAYER, ext_hdr->next_hdr);
  216    }
  217 
  218    EXECUTE_DECODER(next_decoder);
  219 
  220    return NULL;
  221 }
  222 
  223 FUNC_INJECTOR(inject_ip6)
  224 {
  225    struct ip6_header *ip6;
  226    struct ip6_ident *ident;
  227    struct ip6_data *data;
  228    struct ec_session *s = NULL;
  229    u_int32 magic;
  230    u_int16 plen;
  231    u_int16 flen;
  232 
  233 //   DEBUG_MSG("inject_ip6");
  234 
  235    /* i think im paranoid */
  236    if(LENGTH + sizeof(struct ip6_header) > EC_GBL_IFACE->mtu)
  237       return -E_NOTHANDLED;
  238 
  239    /* almost copied from ec_ip.c */
  240    PACKET->packet -= sizeof(struct ip6_header);
  241    ip6 = (struct ip6_header *)PACKET->packet;
  242 
  243    ip6->version = 6;
  244    ip6->next_hdr = PACKET->L4.proto;
  245    ip6->hop_limit = 64;
  246    memcpy(&ip6->saddr, &PACKET->L3.src.addr, IP6_ADDR_LEN);
  247    memcpy(&ip6->daddr, &PACKET->L3.dst.addr, IP6_ADDR_LEN);
  248 
  249    s = PACKET->session;
  250    /* Renew session */
  251    if(session_get(&s, s->ident, sizeof(struct ip6_ident)) == -E_NOTFOUND)
  252       return -E_NOTFOUND;
  253 
  254    ident = s->ident;
  255    memcpy(&ip6->flow_lbl, &ident->flow_lbl, 3);
  256 
  257    data = s->data;
  258    ip6->priority = data->priority;
  259    
  260    flen = LENGTH;
  261    LENGTH += sizeof(struct ip6_header);
  262 
  263    if(s->prev_session != NULL) {
  264       PACKET->session = s->prev_session;
  265       magic = *(u_int32 *) s->prev_session->ident;
  266 
  267       EXECUTE_INJECTOR(CHAIN_LINKED, magic);
  268    } 
  269 
  270    plen = EC_GBL_IFACE->mtu - LENGTH < PACKET->DATA.inject_len
  271           ? EC_GBL_IFACE->mtu - LENGTH : PACKET->DATA.inject_len;
  272    ip6->payload_len = htons(plen);
  273    
  274    PACKET->L3.len = flen + plen;
  275    PACKET->L3.header = (u_char *)ip6;
  276 
  277    if(s->prev_session == NULL) {
  278       PACKET->fwd_packet = PACKET->packet;
  279       PACKET->fwd_len = PACKET->L3.len;
  280    }
  281 
  282    return E_SUCCESS;
  283 }
  284    
  285 static size_t ip6_create_ident(void **i, struct packet_object *po)
  286 {
  287    struct ip6_header *ip6;
  288    struct ip6_ident *ident;
  289 
  290    SAFE_CALLOC(ident, 1, sizeof(struct ip6_ident));
  291 
  292    ip6 = (struct ip6_header *)po->L3.header;
  293 
  294    ident->magic = IP6_MAGIC;
  295    memcpy(&ident->flow_lbl, ip6->flow_lbl, 3);
  296    memcpy(&ident->L3_src, &po->L3.src, sizeof(struct ip_addr));
  297 
  298    *i = ident;
  299 
  300    return sizeof(struct ip6_ident);
  301 }
  302 
  303 static int ip6_match(void *ident_s, void *ident_c)
  304 {
  305    struct ip6_ident *ids = ident_s;
  306    struct ip6_ident *idc = ident_c;
  307 
  308    if(ids->magic != idc->magic)
  309       return 0;
  310 
  311    if(memcmp(&ids->flow_lbl, &idc->flow_lbl, 3))
  312       return 0;
  313    if(ip_addr_cmp(&ids->L3_src, &idc->L3_src))
  314       return 0;
  315 
  316    return 1;
  317 }
  318 
  319 static void ip6_create_session(struct ec_session **s, struct packet_object *po)
  320 {
  321    void *ident;
  322 
  323    DEBUG_MSG("ip6_create_session");
  324 
  325    SAFE_CALLOC(*s, 1, sizeof(struct ec_session));
  326    SAFE_CALLOC((*s)->data, 1, sizeof(struct ip6_data));
  327 
  328    (*s)->data_len = sizeof(struct ip6_data);
  329    (*s)->ident_len = ip6_create_ident(&ident, po);
  330    (*s)->ident = ident;
  331    (*s)->match = &ip6_match;
  332 
  333    return;
  334 }
  335 
  336 /* EOF */
  337 
  338 // vim:ts=3:expandtab
  339