Ejemplo n.º 1
0
int asf_ip_send(struct sk_buff *skb)
{
	struct dst_entry *dst = skb_dst(skb);
	struct neighbour *neigh;
	int res;
	ASFCTRL_FUNC_ENTRY;
	rcu_read_lock();

	neigh = dst_neigh_lookup_skb(dst, skb);
	if (neigh) {
		res = dst_neigh_output(dst, neigh, skb);
		rcu_read_unlock();
		return res;
	}
	rcu_read_unlock();
	ASFCTRL_DBG(" Packet send failure");
	ASFCTRLKernelSkbFree(skb);

	ASFCTRL_FUNC_EXIT;
	return -EINVAL;
}
Ejemplo n.º 2
0
/* Obtain the correct destination MAC address, while preserving the original
 * source MAC address. If we already know this address, we just copy it. If we
 * don't, we use the neighbour framework to find out. In both cases, we make
 * sure that br_handle_frame_finish() is called afterwards.
 */
int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb)
{
	struct neighbour *neigh;
	struct dst_entry *dst;

	skb->dev = bridge_parent(skb->dev);
	if (!skb->dev)
		goto free_skb;
	dst = skb_dst(skb);
	neigh = dst_neigh_lookup_skb(dst, skb);
	if (neigh) {
		struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
		int ret;

		if (neigh->hh.hh_len) {
			neigh_hh_bridge(&neigh->hh, skb);
			skb->dev = nf_bridge->physindev;
			ret = br_handle_frame_finish(net, sk, skb);
		} else {
			/* the neighbour function below overwrites the complete
			 * MAC header, so we save the Ethernet source address and
			 * protocol number.
			 */
			skb_copy_from_linear_data_offset(skb,
							 -(ETH_HLEN-ETH_ALEN),
							 nf_bridge->neigh_header,
							 ETH_HLEN-ETH_ALEN);
			/* tell br_dev_xmit to continue with forwarding */
			nf_bridge->bridged_dnat = 1;
			/* FIXME Need to refragment */
			ret = neigh->output(neigh, skb);
		}
		neigh_release(neigh);
		return ret;
	}
free_skb:
	kfree_skb(skb);
	return 0;
}
Ejemplo n.º 3
0
static int ak_client_inform_port(const struct net_device *dev, aku16 port_src,
                                 aku8 protocol, unsigned int uid)
{
  ak_client_logon_array user_logon[AK_CLIENT_MAX_LOGONS_PER_USER];
  struct sk_buff *skb;			// Pacote a ser enviado para avisar o firewall
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
  struct flowi flp;
#else
  struct flowi4 flp;
#endif
  struct in_device *idev;
  struct rtable *rt;			// Rota a ser usada para enviar o pacote
  struct iphdr *ip;			// Header IP do pacote a enviar
  struct udphdr *udp;			// Header UDP do pacote a enviar
  struct dst_entry *dst;
#if (((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)) && \
    (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))) || \
    (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)))
  struct neighbour *neigh;
#endif
  MD5_CTX contexto;			// Contexto para calcular MD5
  int pkt_sent = 0;			// Enviou ao menos um pacote ?
  fwprofd_header *header;
  fwprofd_port_ctl *port_ctl;
  ak_client_logon_array *logon;
  int size;
  int count;
  int i;

  if (!dev)
  {
    PRINT("Device de saida NULL\n");
    return -2;
  }
  count = ak_client_get_user_list(uid, user_logon);
  size = sizeof(struct iphdr) + sizeof(struct udphdr) + sizeof(fwprofd_header) + sizeof(fwprofd_port_ctl);

  for (i = 0, logon = user_logon; i < count; i++, logon++)
  {
    PRINT("Enviando pacote %d/%d - ", i + 1, count);

    skb = alloc_skb(size + 16, GFP_ATOMIC);
    if (!skb)
    {
      PRINT("Nao consegui alocar skbuff para enviar pacote\n");
      return -3;
    }
    skb->data += 16;
    skb->len = size;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22))
    skb->tail = skb->data + size;
    skb->nh.iph = (struct iphdr *) skb->data;
    skb->h.uh = (struct udphdr *) (skb->data + sizeof(struct iphdr));
    ip = skb->nh.iph;
#else
    skb_set_tail_pointer(skb, size);
    skb_reset_network_header(skb);
    skb_set_transport_header(skb, sizeof(struct iphdr));
    ip = ip_hdr(skb);
#endif
    udp = (struct udphdr *) ((char *) ip + sizeof(struct iphdr));
    header = (fwprofd_header *) (udp + 1);
    port_ctl = (fwprofd_port_ctl *) (header + 1);

    // Pega o IP da interface de saida para alocar rota de saida

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
    idev = in_dev_get(dev);
#else
    rcu_read_lock();
    idev = __in_dev_get_rcu(dev);
#endif

    if (!idev)
    {
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
      rcu_read_unlock();
#endif
      kfree_skb(skb);
      PRINT("Device de saida sem IP (1)\n");
      return -4;
    }
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
    read_lock(&idev->lock);
#endif

    if (!idev->ifa_list)
    {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
      read_unlock(&idev->lock);
      in_dev_put(idev);
#else
      rcu_read_unlock();
#endif
      kfree_skb(skb);
      PRINT("Device de saida sem IP (2)\n");
      return -5;
    }
    ip->saddr = idev->ifa_list->ifa_address;

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
    read_unlock(&idev->lock);
    in_dev_put(idev);
#else
    rcu_read_unlock();
#endif


#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
    flp.oif = 0;
    flp.nl_u.ip4_u.saddr = ip->saddr;
    flp.nl_u.ip4_u.daddr = logon->logon_data.ip.s_addr;
    flp.nl_u.ip4_u.tos = 0;
    flp.uli_u.ports.sport = ntohs(AKER_PROF_PORT);
    flp.uli_u.ports.dport = ntohs(AKER_PROF_PORT);
    flp.proto = IPPROTO_UDP;
#else
    flp.flowi4_oif = 0;
    flp.saddr = ip->saddr;
    flp.daddr = logon->logon_data.ip.s_addr;
    flp.flowi4_tos = 0;
    flp.fl4_sport = ntohs(AKER_PROF_PORT);
    flp.fl4_dport = ntohs(AKER_PROF_PORT);
    flp.flowi4_proto = IPPROTO_UDP;
#endif


#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25))
    if (ip_route_output_key(&rt, &flp))
#else
    if (ip_route_output_key(&init_net, &rt, &flp))
#endif
    {
      kfree_skb(skb);
      PRINT("Erro ao alocar rota de saida\n");
      continue;
    }
#else
    rt = ip_route_output_key(&init_net, &flp);
    if (IS_ERR(rt))
    {
      kfree_skb(skb);
      PRINT("Erro ao alocar rota de saida\n");
      continue;
    }
#endif

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
    skb->dst = dst_clone(&rt->u.dst);
#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
    skb_dst_set(skb, dst_clone(&rt->u.dst));
#else
    skb_dst_set(skb, dst_clone(&rt->dst));
#endif

#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36))
    skb->dev = rt->u.dst.dev;
#else
    skb->dev = rt->dst.dev;
#endif
    skb->protocol = __constant_htons(ETH_P_IP);

    // Preenche dados do usuario

    port_ctl->ip_src.s_addr = 0;
    port_ctl->seq = ntohl(logon->seq);		// ak_client_get_user_list() ja incrementou seq
    port_ctl->user_num = ntohl(logon->logon_data.ak_user_num);
    port_ctl->port = port_src;
    port_ctl->protocol = protocol;
    port_ctl->reserved = 0;

    MD5Init(&contexto);
    MD5Update(&contexto, (u_char *) logon->logon_data.secret, 16);
    MD5Update(&contexto, (u_char *) &port_ctl->ip_src, sizeof(struct in_addr));
    MD5Update(&contexto, (u_char *) &port_ctl->seq, sizeof(aku32));
    MD5Update(&contexto, (u_char *) &port_ctl->user_num, sizeof(aku32));
    MD5Update(&contexto, (u_char *) &port_ctl->port, sizeof(aku16));
    MD5Update(&contexto, (u_char *) &port_ctl->protocol, sizeof(aku8));
    MD5Update(&contexto, (u_char *) &port_ctl->reserved, sizeof(aku8));
    MD5Final((u_char *) port_ctl->hash, &contexto);

    // Preenche demais campos do pacote

    header->ip_dst = logon->logon_data.ip;
    header->versao = AKER_PROF_VERSION;
    header->tipo_req = APROF_BIND_PORT;
    memset(header->md5, 0, 16);

    MD5Init(&contexto);
    MD5Update(&contexto, (void *) header, sizeof(fwprofd_header));
    MD5Update(&contexto, (void *) port_ctl, sizeof(fwprofd_port_ctl));
    MD5Final(header->md5, &contexto);

    udp->dest = udp->source = ntohs(AKER_PROF_PORT);
    udp->len = ntohs(size - sizeof(struct iphdr));
    udp->check = 0;

    ip->ihl = sizeof(struct iphdr) >> 2;
    ip->version = IPVERSION;
    ip->ttl = IPDEFTTL;
    ip->tos = 0;
    ip->daddr = header->ip_dst.s_addr;
    ip->protocol = IPPROTO_UDP;
    ip->frag_off = 0;
    ip->tot_len = htons(size);
    ip->id = 0;
    ip->check = 0;
    ip->check = ip_fast_csum((u_char *) ip, ip->ihl);
    PRINT("%s -> %s\n", ip2a(ip->saddr), ip2a(ip->daddr));

    // Envia pacote
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31))
    dst = skb->dst;
#else
    dst = skb_dst(skb);
#endif

#if (((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)) && \
    (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))) || \
    (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)) && \
    LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0))

    rcu_read_lock();
    neigh = dst_get_neighbour_noref(dst);
    
    if (neigh)
    {
      neigh->output(neigh, skb);
      ip_rt_put(rt);
      pkt_sent++;
    }

#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
    rcu_read_lock();
    neigh = dst_neigh_lookup_skb(dst, skb);

    if (neigh)
    {
      neigh->output(neigh, skb);
      ip_rt_put(rt);
      pkt_sent++;
    }
#else
    if (dst->hh)
    {
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))
      int hh_alen;

      read_lock_bh(dst->hh->hh_lock);
      hh_alen = HH_DATA_ALIGN(dst->hh->hh_len);
      memcpy(skb->data - hh_alen, dst->hh->hh_data, hh_alen);
      read_unlock_bh(dst->hh->hh_lock);
      skb_push(skb, dst->hh->hh_len);
      dst->hh->hh_output(skb);
#else
      neigh_hh_output(dst->hh, skb);
#endif
      ip_rt_put(rt);
      pkt_sent++;
    }
    else if (dst->neighbour)
    {
      dst->neighbour->output(skb);
      ip_rt_put(rt);
      pkt_sent++;
    }
#endif
    else
    {
      kfree_skb(skb);
      ip_rt_put(rt);
      PRINT("Nao sei como enviar pacote de saida\n");
    }

#if (((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41)) && \
    (LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0))) || \
    (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)))
    rcu_read_unlock();
#endif
  }
  if (!pkt_sent)
    return -1;

  return 0;
}