Exemple #1
0
volatile struct sock *get_sock (struct proto *prot, unsigned short num,
				unsigned long raddr,
				unsigned short rnum, unsigned long laddr)
{
  volatile struct sock *s;
  PRINTK ("get_sock (prot=%X, num=%d, raddr=%X, rnum=%d, laddr=%X)\n",
	  prot, num, raddr, rnum, laddr);

  /* SOCK_ARRAY_SIZE must be a power of two.  This will work better
     than a prime unless 3 or more sockets end up using the same
     array entry.  This should not be a problem because most
     well known sockets don't overlap that much, and for
     the other ones, we can just be careful about picking our
     socket number when we choose an arbitrary one. */

  for (s=prot->sock_array[num&(SOCK_ARRAY_SIZE-1)]; s != NULL; s=s->next)
    {
      if (s->num == num)
	{
	  /* we need to see if this is the socket that we want. */
	  if (!ip_addr_match (s->daddr, raddr))
	    continue;
	  if (s->dummy_th.dest != rnum && s->dummy_th.dest != 0)
	    continue;
	  if (!ip_addr_match (s->saddr, laddr))
	    continue;
	  return (s);
	}
    }
  return (NULL);
}
Exemple #2
0
/*
 * Handle IP packets coming from the polled ethernet interface.
 */
void
__ip_handler(pktbuf_t *pkt, enet_addr_t *src_enet_addr)
{
    ip_header_t *ip = pkt->ip_hdr;
    ip_route_t  r;
    int         hdr_bytes;

    /* first make sure its ours and has a good checksum. */
    if (!ip_addr_match(ip->destination) ||
	__sum((word *)ip, ip->hdr_len << 2, 0) != 0) {
	__pktbuf_free(pkt);
	return;
    }

    memcpy(r.ip_addr, ip->source, sizeof(ip_addr_t));
    memcpy(r.enet_addr, src_enet_addr, sizeof(enet_addr_t));

    hdr_bytes = ip->hdr_len << 2;
    pkt->pkt_bytes = ntohs(ip->length) - hdr_bytes;

    switch (ip->protocol) {

#if NET_SUPPORT_ICMP
      case IP_PROTO_ICMP:
	pkt->icmp_hdr = (icmp_header_t *)(((char *)ip) + hdr_bytes);
	__icmp_handler(pkt, &r);
	break;
#endif

#if NET_SUPPORT_TCP
      case IP_PROTO_TCP:
	pkt->tcp_hdr = (tcp_header_t *)(((char *)ip) + hdr_bytes);
	__tcp_handler(pkt, &r);
	break;
#endif

#if NET_SUPPORT_UDP
      case IP_PROTO_UDP:
	pkt->udp_hdr = (udp_header_t *)(((char *)ip) + hdr_bytes);
	__udp_handler(pkt, &r);
	break;
#endif

      default:
	__pktbuf_free(pkt);
	break;
    }
}
Exemple #3
0
static void handle_ip_packet(struct ip* iptr, int hw_dir)
{
    int direction = 0; /* incoming */
    history_type* ht;
    union {
      history_type **ht_pp;
      void **void_pp;
    } u_ht = { &ht };
    addr_pair ap;
    unsigned int len = 0;
    struct in6_addr scribdst;   /* Scratch pad. */
    struct in6_addr scribsrc;   /* Scratch pad. */
    /* Reinterpret packet type. */
    struct ip6_hdr* ip6tr = (struct ip6_hdr *) iptr;

    memset(&ap, '\0', sizeof(ap));

    if( (IP_V(iptr) ==4 && options.netfilter == 0)
            || (IP_V(iptr) == 6 && options.netfilter6 == 0) ) { 
        /*
         * Net filter is off, so assign direction based on MAC address
         */
        if(hw_dir == 1) {
            /* Packet leaving this interface. */
            assign_addr_pair(&ap, iptr, 0);
            direction = 1;
        }
        else if(hw_dir == 0) {
            /* Packet incoming */
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        /* Packet direction is not given away by h/ware layer.  Try IP
         * layer
         */
        else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_src)) {
            /* outgoing */
            assign_addr_pair(&ap, iptr, 0);
            direction = 1;
        }
        else if((IP_V(iptr) == 4) && have_ip_addr && ip_addr_match(iptr->ip_dst)) {
            /* incoming */
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_src)) {
            /* outgoing */
            assign_addr_pair(&ap, iptr, 0);
            direction = 1;
        }
        else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
            /* incoming */
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        /*
         * Cannot determine direction from hardware or IP levels.  Therefore 
         * assume that it was a packet between two other machines, assign
         * source and dest arbitrarily (by numerical value) and account as 
         * incoming.
         */
	else if (options.promiscuous_but_choosy) {
	    return;		/* junk it */
	}
        else if((IP_V(iptr) == 4) && (iptr->ip_src.s_addr < iptr->ip_dst.s_addr)) {
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        else if(IP_V(iptr) == 4) {
            assign_addr_pair(&ap, iptr, 0);
            direction = 0;
        }
        /* Drop other uncertain packages. */
    }

    if(IP_V(iptr) == 4 && options.netfilter != 0) {
        /* 
         * Net filter on, assign direction according to netmask 
         */ 
        if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
            /* out of network */
            assign_addr_pair(&ap, iptr, 0);
            direction = 1;
        }
        else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
            /* into network */
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        else {
            /* drop packet */
            return ;
        }
    }

    if(IP_V(iptr) == 6 && options.netfilter6 != 0) {
        /*
         * Net filter IPv6 active.
         */
        int j;
        //else if((IP_V(iptr) == 6) && have_ip6_addr && ip6_addr_match(&ip6tr->ip6_dst)) {
        /* First reduce the participating addresses using the netfilter prefix.
         * We need scratch pads to do this.
         */
        for (j=0; j < 16; ++j) {
            scribdst.s6_addr[j] = ip6tr->ip6_dst.s6_addr[j]
                                        & options.netfilter6mask.s6_addr[j];
            scribsrc.s6_addr[j] = ip6tr->ip6_src.s6_addr[j]
                                        & options.netfilter6mask.s6_addr[j];
        }

        /* Now look for any hits. */
        //if(in_filter_net(iptr->ip_src) && !in_filter_net(iptr->ip_dst)) {
        if (IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
                && ! IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
            /* out of network */
            assign_addr_pair(&ap, iptr, 0);
            direction = 1;
        }
        //else if(in_filter_net(iptr->ip_dst) && !in_filter_net(iptr->ip_src)) {
        else if (! IN6_ARE_ADDR_EQUAL(&scribsrc, &options.netfilter6net)
                    && IN6_ARE_ADDR_EQUAL(&scribdst, &options.netfilter6net)) {
            /* into network */
            assign_addr_pair(&ap, iptr, 1);
            direction = 0;
        }
        else {
            /* drop packet */
            return ;
        }
    }

#if 1
    /* Test if link-local IPv6 packets should be dropped. */
    if( IP_V(iptr) == 6 && !options.link_local
            && (IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_dst)
                || IN6_IS_ADDR_LINKLOCAL(&ip6tr->ip6_src)) )
        return;
#endif

    /* Do address resolving. */
    switch (IP_V(iptr)) {
      case 4:
          ap.protocol = iptr->ip_p;
          /* Add the addresses to be resolved */
          /* The IPv4 address is embedded in a in6_addr structure,
           * so it need be copied, and delivered to resolve(). */
          memset(&scribdst, '\0', sizeof(scribdst));
          memcpy(&scribdst, &iptr->ip_dst, sizeof(struct in_addr));
          resolve(ap.af, &scribdst, NULL, 0);
          memset(&scribsrc, '\0', sizeof(scribsrc));
          memcpy(&scribsrc, &iptr->ip_src, sizeof(struct in_addr));
          resolve(ap.af, &scribsrc, NULL, 0);
          break;
      case 6:
          ap.protocol = ip6tr->ip6_nxt;
          /* Add the addresses to be resolved */
          resolve(ap.af, &ip6tr->ip6_dst, NULL, 0);
          resolve(ap.af, &ip6tr->ip6_src, NULL, 0);
      default:
          break;
    }


    if(hash_find(history, &ap, u_ht.void_pp) == HASH_STATUS_KEY_NOT_FOUND) {
        ht = history_create();
        hash_insert(history, &ap, ht);
    }

    /* Do accounting. */
    switch (IP_V(iptr)) {
      case 4:
          len = ntohs(iptr->ip_len);
          break;
      case 6:
          len = ntohs(ip6tr->ip6_plen) + 40;
      default:
          break;
    }

    /* Update record */
    ht->last_write = history_pos;
    if( ((IP_V(iptr) == 4) && (iptr->ip_src.s_addr == ap.src.s_addr))
       || ((IP_V(iptr) == 6) && !memcmp(&ip6tr->ip6_src, &ap.src6, sizeof(ap.src6))) )
    {
        ht->sent[history_pos] += len;
        ht->total_sent += len;
    }
    else {
        ht->recv[history_pos] += len;
        ht->total_recv += len;
    }

    if(direction == 0) {
        /* incoming */
        history_totals.recv[history_pos] += len;
        history_totals.total_recv += len;
    }
    else {
        history_totals.sent[history_pos] += len;
        history_totals.total_sent += len;
    }
    
}