Exemplo n.º 1
0
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
	struct net_bridge_port *p;

	if (dev->br_port != NULL)
		return -EBUSY;

#if 0
	if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
		return -EINVAL;
#endif

	if (dev->hard_start_xmit == br_dev_xmit)
		return -ELOOP;

	if (!is_valid_ether_addr(dev->dev_addr))
		return -EADDRNOTAVAIL;

	dev_hold(dev);
	write_lock_bh(&br->lock);
	if ((p = new_nbp(br, dev)) == NULL) {
		write_unlock_bh(&br->lock);
		dev_put(dev);
		return -EXFULL;
	}

	dev_set_promiscuity(dev, 1);

	br_stp_recalculate_bridge_id(br);
	br_fdb_insert(br, p, dev->dev_addr, 1);
	if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
		br_stp_enable_port(p);
	write_unlock_bh(&br->lock);

	return 0;
}
Exemplo n.º 2
0
/* Call this every MPC-p2 seconds... Not exactly correct solution,
   but an easy one... */
static void clear_count_and_expired(struct mpoa_client *client)
{
    in_cache_entry *entry, *next_entry;
    struct timeval now;

    do_gettimeofday(&now);

    write_lock_bh(&client->ingress_lock);
    entry = client->in_cache;
    while(entry != NULL) {
        entry->count=0;
        next_entry = entry->next;
        if((now.tv_sec - entry->tv.tv_sec)
                > entry->ctrl_info.holding_time) {
            dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %pI4\n",
                    &entry->ctrl_info.in_dst_ip);
            client->in_ops->remove_entry(entry, client);
        }
        entry = next_entry;
    }
    write_unlock_bh(&client->ingress_lock);

    return;
}
Exemplo n.º 3
0
struct in_device *inetdev_init(struct net_device *dev)
{
	struct in_device *in_dev;

	ASSERT_RTNL();

	in_dev = kmalloc(sizeof(*in_dev), GFP_KERNEL);
	if (!in_dev)
		return NULL;
	memset(in_dev, 0, sizeof(*in_dev));
	in_dev->lock = RW_LOCK_UNLOCKED;
	memcpy(&in_dev->cnf, &ipv4_devconf_dflt, sizeof(in_dev->cnf));
	in_dev->cnf.sysctl = NULL;
	in_dev->dev = dev;
	if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) {
		kfree(in_dev);
		return NULL;
	}
	inet_dev_count++;
	/* Reference in_dev->dev */
	dev_hold(dev);
#ifdef CONFIG_SYSCTL
	neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
#endif
	write_lock_bh(&inetdev_lock);
	dev->ip_ptr = in_dev;
	/* Account for reference dev->ip_ptr */
	in_dev_hold(in_dev);
	write_unlock_bh(&inetdev_lock);
#ifdef CONFIG_SYSCTL
	devinet_sysctl_register(in_dev, &in_dev->cnf);
#endif
	if (dev->flags&IFF_UP)
		ip_mc_up(in_dev);
	return in_dev;
}
Exemplo n.º 4
0
static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
{
	struct sockaddr_sco *sa = (struct sockaddr_sco *) addr;
	struct sock *sk = sock->sk;
	bdaddr_t *src = &sa->sco_bdaddr;
	int err = 0;

	BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr));

	if (!addr || addr->sa_family != AF_BLUETOOTH)
		return -EINVAL;

	lock_sock(sk);

	if (sk->state != BT_OPEN) {
		err = -EBADFD;
		goto done;
	}

	write_lock_bh(&sco_sk_list.lock);

	if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) {
		err = -EADDRINUSE;
	} else {
	/* Save source address */
	bacpy(&bluez_pi(sk)->src, &sa->sco_bdaddr);
	sk->state = BT_BOUND;
	}

	write_unlock_bh(&sco_sk_list.lock);

done:
	release_sock(sk);

	return err;
}
Exemplo n.º 5
0
static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
					  struct mpoa_client *client)
{
	in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);

	if (entry == NULL) {
		printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
		return NULL;
	}

	dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", NIPQUAD(dst_ip));
	memset(entry,0,sizeof(in_cache_entry));

	atomic_set(&entry->use, 1);
	dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
	write_lock_bh(&client->ingress_lock);
	entry->next = client->in_cache;
	entry->prev = NULL;
	if (client->in_cache != NULL)
		client->in_cache->prev = entry;
	client->in_cache = entry;

	memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
	entry->ctrl_info.in_dst_ip = dst_ip;
	do_gettimeofday(&(entry->tv));
	entry->retry_time = client->parameters.mpc_p4;
	entry->count = 1;
	entry->entry_state = INGRESS_INVALID;
	entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
	atomic_inc(&entry->use);

	write_unlock_bh(&client->ingress_lock);
	dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");

	return entry;
}
Exemplo n.º 6
0
int nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
{
	int ret = 0;

	if (l4proto->l3proto >= PF_MAX) {
		ret = -EBUSY;
		goto out;
	}

	if (l4proto == &nf_conntrack_l4proto_generic) {
		nf_ct_l4proto_unregister_sysctl(l4proto);
		goto out;
	}

	write_lock_bh(&nf_conntrack_lock);
	if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
	    != l4proto) {
		write_unlock_bh(&nf_conntrack_lock);
		ret = -EBUSY;
		goto out;
	}
	nf_ct_protos[l4proto->l3proto][l4proto->l4proto]
		= &nf_conntrack_l4proto_generic;
	write_unlock_bh(&nf_conntrack_lock);

	nf_ct_l4proto_unregister_sysctl(l4proto);

	/* Somebody could be still looking at the proto in bh. */
	synchronize_net();

	/* Remove all contrack entries for this protocol */
	nf_ct_iterate_cleanup(kill_l4proto, l4proto);

out:
	return ret;
}
Exemplo n.º 7
0
struct socket *rds_tcp_listen_init(struct net *net)
{
	struct sockaddr_in sin;
	struct socket *sock = NULL;
	int ret;

	ret = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
	if (ret < 0)
		goto out;

	sock->sk->sk_reuse = SK_CAN_REUSE;
	rds_tcp_nonagle(sock);

	write_lock_bh(&sock->sk->sk_callback_lock);
	sock->sk->sk_user_data = sock->sk->sk_data_ready;
	sock->sk->sk_data_ready = rds_tcp_listen_data_ready;
	write_unlock_bh(&sock->sk->sk_callback_lock);

	sin.sin_family = PF_INET;
	sin.sin_addr.s_addr = (__force u32)htonl(INADDR_ANY);
	sin.sin_port = (__force u16)htons(RDS_TCP_PORT);

	ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
	if (ret < 0)
		goto out;

	ret = sock->ops->listen(sock, 64);
	if (ret < 0)
		goto out;

	return sock;
out:
	if (sock)
		sock_release(sock);
	return NULL;
}
Exemplo n.º 8
0
void br_fdb_changeaddr(struct net_bridge_port *p, unsigned char *newaddr)
{
	struct net_bridge *br;
	int i;

	br = p->br;
	write_lock_bh(&br->hash_lock);
	for (i=0;i<BR_HASH_SIZE;i++) {
		struct net_bridge_fdb_entry *f;

		f = br->hash[i];
		while (f != NULL) {
			if (f->dst == p && f->is_local) {
				__hash_unlink(f);
				memcpy(f->addr.addr, newaddr, ETH_ALEN);
				__hash_link(br, f, br_mac_hash(newaddr));
				write_unlock_bh(&br->hash_lock);
				return;
			}
			f = f->next_hash;
		}
	}
	write_unlock_bh(&br->hash_lock);
}
Exemplo n.º 9
0
static void socket_open_server(struct diag_socket_info *info)
{
	int ret = 0;
	struct sockaddr_msm_ipc srv_addr = { 0 };

	if (!info)
		return;

	ret = sock_create(AF_MSM_IPC, SOCK_DGRAM, 0, &info->hdl);
	if (ret < 0 || !info->hdl) {
		pr_err("diag: In %s, socket not initialized for %s\n", __func__,
		       info->name);
		return;
	}

	write_lock_bh(&info->hdl->sk->sk_callback_lock);
	info->hdl->sk->sk_user_data = (void *)(info);
	info->hdl->sk->sk_data_ready = socket_data_ready;
	info->hdl->sk->sk_write_space = socket_flow_cntl;
	write_unlock_bh(&info->hdl->sk->sk_callback_lock);

	srv_addr.family = AF_MSM_IPC;
	srv_addr.address.addrtype = MSM_IPC_ADDR_NAME;
	srv_addr.address.addr.port_name.service = info->svc_id;
	srv_addr.address.addr.port_name.instance = info->ins_id;

	ret = kernel_bind(info->hdl, (struct sockaddr *)&srv_addr,
			  sizeof(srv_addr));
	if (ret) {
		pr_err("diag: In %s, failed to bind, ch: %s, svc_id: %d ins_id: %d, err: %d\n",
		       __func__, info->name, info->svc_id, info->ins_id, ret);
		return;
	}
	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s opened server svc: %d ins: %d",
		 info->name, info->svc_id, info->ins_id);
}
Exemplo n.º 10
0
static void smc_buf_unuse(struct smc_connection *conn,
			  struct smc_link_group *lgr)
{
	if (conn->sndbuf_desc)
		conn->sndbuf_desc->used = 0;
	if (conn->rmb_desc) {
		if (!conn->rmb_desc->regerr) {
			conn->rmb_desc->used = 0;
			if (!lgr->is_smcd) {
				/* unregister rmb with peer */
				smc_llc_do_delete_rkey(
						&lgr->lnk[SMC_SINGLE_LINK],
						conn->rmb_desc);
			}
		} else {
			/* buf registration failed, reuse not possible */
			write_lock_bh(&lgr->rmbs_lock);
			list_del(&conn->rmb_desc->list);
			write_unlock_bh(&lgr->rmbs_lock);

			smc_buf_free(lgr, true, conn->rmb_desc);
		}
	}
}
Exemplo n.º 11
0
/**
 * xs_close - close a socket
 * @xprt: transport
 *
 * This is used when all requests are complete; ie, no DRC state remains
 * on the server we want to save.
 */
static void xs_close(struct rpc_xprt *xprt)
{
	struct socket *sock = xprt->sock;
	struct sock *sk = xprt->inet;

	if (!sk)
		return;

	dprintk("RPC:      xs_close xprt %p\n", xprt);

	write_lock_bh(&sk->sk_callback_lock);
	xprt->inet = NULL;
	xprt->sock = NULL;

	sk->sk_user_data = NULL;
	sk->sk_data_ready = xprt->old_data_ready;
	sk->sk_state_change = xprt->old_state_change;
	sk->sk_write_space = xprt->old_write_space;
	write_unlock_bh(&sk->sk_callback_lock);

	sk->sk_no_check = 0;

	sock_release(sock);
}
Exemplo n.º 12
0
void tcf_police_destroy(struct tcf_police *p)
{
	unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
	struct tcf_common **p1p;

	for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
		if (*p1p == &p->common) {
			write_lock_bh(&police_lock);
			*p1p = p->tcf_next;
			write_unlock_bh(&police_lock);
#ifdef CONFIG_NET_ESTIMATOR
			gen_kill_estimator(&p->tcf_bstats,
					   &p->tcf_rate_est);
#endif
			if (p->tcfp_R_tab)
				qdisc_put_rtab(p->tcfp_R_tab);
			if (p->tcfp_P_tab)
				qdisc_put_rtab(p->tcfp_P_tab);
			kfree(p);
			return;
		}
	}
	BUG_TRAP(0);
}
Exemplo n.º 13
0
int ax25_protocol_register(unsigned int pid,
	int (*func)(struct sk_buff *, ax25_cb *))
{
	struct protocol_struct *protocol;

	if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
		return 0;
#ifdef CONFIG_INET
	if (pid == AX25_P_IP || pid == AX25_P_ARP)
		return 0;
#endif
	if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL)
		return 0;

	protocol->pid  = pid;
	protocol->func = func;

	write_lock_bh(&protocol_list_lock);
	protocol->next = protocol_list;
	protocol_list  = protocol;
	write_unlock_bh(&protocol_list_lock);

	return 1;
}
void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
{
    struct ip_mc_list *i, **ip;

    ASSERT_RTNL();

    for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
        if (i->multiaddr==addr) {
            if (--i->users == 0) {
                write_lock_bh(&in_dev->lock);
                *ip = i->next;
                write_unlock_bh(&in_dev->lock);
                igmp_group_dropped(i);

                if (in_dev->dev->flags & IFF_UP)
                    ip_rt_multicast_event(in_dev);

                ip_ma_put(i);
                return;
            }
            break;
        }
    }
}
Exemplo n.º 15
0
/*
 * 	inserts (in front) a new entry in hash table, 
 * 	called from ipsec_alg_register() when new algorithm is registered.
 */
static int ipsec_alg_insert(struct ipsec_alg *ixt) {
	int ret=-EINVAL;
	unsigned hashval=ipsec_alg_hashfn(ixt->ixt_alg_type, ixt->ixt_alg_id);
	struct list_head *head= ipsec_alg_hash_table + hashval;
	/* 	new element must be virgin ... */
	if (ixt->ixt_list.next != &ixt->ixt_list || 
		ixt->ixt_list.prev != &ixt->ixt_list) {
		printk(KERN_ERR "%s: ixt object \"%s\" "
				"list head not initialized\n",
				__FUNCTION__, ixt->ixt_name);
		return ret;
	}
	write_lock_bh(&ipsec_alg_lock);
	if (__ipsec_alg_find(ixt->ixt_alg_type, ixt->ixt_alg_id, head))
		barf_out(KERN_WARNING "ipsec_alg for alg_type=%d, alg_id=%d already exist."
				"Not loaded (ret=%d).\n",
				ixt->ixt_alg_type,
				ixt->ixt_alg_id, ret=-EEXIST);
	list_add(&ixt->ixt_list, head);
	ret=0;
out:
	write_unlock_bh(&ipsec_alg_lock);
	return ret;
}
Exemplo n.º 16
0
static int fl_intern(struct ip6_flowlabel *fl, __be32 label)
{
	fl->label = label & IPV6_FLOWLABEL_MASK;

	write_lock_bh(&ip6_fl_lock);
	if (label == 0) {
		for (;;) {
			fl->label = htonl(net_random())&IPV6_FLOWLABEL_MASK;
			if (fl->label) {
				struct ip6_flowlabel *lfl;
				lfl = __fl_lookup(fl->label);
				if (lfl == NULL)
					break;
			}
		}
	}

	fl->lastuse = jiffies;
	fl->next = fl_ht[FL_HASH(fl->label)];
	fl_ht[FL_HASH(fl->label)] = fl;
	atomic_inc(&fl_size);
	write_unlock_bh(&ip6_fl_lock);
	return 0;
}
Exemplo n.º 17
0
static int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target)
{
	__be32 *targets = bond->params.arp_targets;
	struct list_head *iter;
	struct slave *slave;
	unsigned long *targets_rx;
	int ind, i;

	if (IS_IP_TARGET_UNUSABLE_ADDRESS(target)) {
		pr_err("%s: invalid ARP target %pI4 specified for removal\n",
		       bond->dev->name, &target);
		return -EINVAL;
	}

	ind = bond_get_targets_ip(targets, target);
	if (ind == -1) {
		pr_err("%s: unable to remove nonexistent ARP target %pI4\n",
		       bond->dev->name, &target);
		return -EINVAL;
	}

	if (ind == 0 && !targets[1] && bond->params.arp_interval)
		pr_warn("%s: Removing last arp target with arp_interval on\n",
			bond->dev->name);

	pr_info("%s: Removing ARP target %pI4\n", bond->dev->name, &target);

	/* not to race with bond_arp_rcv */
	write_lock_bh(&bond->lock);

	bond_for_each_slave(bond, slave, iter) {
		targets_rx = slave->target_last_arp_rx;
		for (i = ind; (i < BOND_MAX_ARP_TARGETS-1) && targets[i+1]; i++)
			targets_rx[i] = targets_rx[i+1];
		targets_rx[i] = 0;
	}
Exemplo n.º 18
0
static void rfc2863_policy(struct net_device *dev)
{
	unsigned char operstate = default_operstate(dev);

	if (operstate == dev->operstate)
		return;

	write_lock_bh(&dev_base_lock);

	switch(dev->link_mode) {
	case IF_LINK_MODE_DORMANT:
		if (operstate == IF_OPER_UP)
			operstate = IF_OPER_DORMANT;
		break;

	case IF_LINK_MODE_DEFAULT:
	default:
		break;
	}

	dev->operstate = operstate;

	write_unlock_bh(&dev_base_lock);
}
Exemplo n.º 19
0
static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
	__be32 dst_ip = msg->content.in_info.in_dst_ip;
	__be32 mask = msg->ip_mask;
	in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);

	if (entry == NULL) {
		pr_info("(%s) purge for a non-existing entry, ip = %pI4\n",
			mpc->dev->name, &dst_ip);
		return;
	}

	do {
		dprintk("(%s) removing an ingress entry, ip = %pI4\n",
			mpc->dev->name, &dst_ip);
		write_lock_bh(&mpc->ingress_lock);
		mpc->in_ops->remove_entry(entry, mpc);
		write_unlock_bh(&mpc->ingress_lock);
		mpc->in_ops->put(entry);
		entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
	} while (entry != NULL);

	return;
}
Exemplo n.º 20
0
/**
 *  udp_lib_get_port  -  UDP/-Lite port lookup for IPv4 and IPv6
 *
 *  @sk:          socket struct in question
 *  @snum:        port number to look up
 *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
 */
int udp_lib_get_port(struct sock *sk, unsigned short snum,
		       int (*saddr_comp)(const struct sock *sk1,
					 const struct sock *sk2 )    )
{
	struct hlist_head *udptable = sk->sk_prot->h.udp_hash;
	struct hlist_node *node;
	struct hlist_head *head;
	struct sock *sk2;
	int    error = 1;
	struct net *net = sock_net(sk);

	write_lock_bh(&udp_hash_lock);

	if (!snum) {
		int i, low, high, remaining;
		unsigned rover, best, best_size_so_far;

		inet_get_local_port_range(&low, &high);
		remaining = (high - low) + 1;

		best_size_so_far = UINT_MAX;
		best = rover = net_random() % remaining + low;

		/* 1st pass: look for empty (or shortest) hash chain */
		for (i = 0; i < UDP_HTABLE_SIZE; i++) {
			int size = 0;

			head = &udptable[udp_hashfn(net, rover)];
			if (hlist_empty(head))
				goto gotit;

			sk_for_each(sk2, node, head) {
				if (++size >= best_size_so_far)
					goto next;
			}
			best_size_so_far = size;
			best = rover;
		next:
			/* fold back if end of range */
			if (++rover > high)
				rover = low + ((rover - low)
					       & (UDP_HTABLE_SIZE - 1));


		}

		/* 2nd pass: find hole in shortest hash chain */
		rover = best;
		for (i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++) {
			if (! __udp_lib_lport_inuse(net, rover, udptable))
				goto gotit;
			rover += UDP_HTABLE_SIZE;
			if (rover > high)
				rover = low + ((rover - low)
					       & (UDP_HTABLE_SIZE - 1));
		}


		/* All ports in use! */
		goto fail;

gotit:
		snum = rover;
	} else {
Exemplo n.º 21
0
static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
{
	struct sock *sk = sock->sk;
	struct sockaddr_l2 la;
	int len, err = 0;

	BT_DBG("sk %p", sk);

	if (!addr || addr->sa_family != AF_BLUETOOTH)
		return -EINVAL;

	memset(&la, 0, sizeof(la));
	len = min_t(unsigned int, sizeof(la), alen);
	memcpy(&la, addr, len);

	if (la.l2_cid && la.l2_psm)
		return -EINVAL;

	lock_sock(sk);

	if (sk->sk_state != BT_OPEN) {
		err = -EBADFD;
		goto done;
	}

	if (la.l2_psm) {
		__u16 psm = __le16_to_cpu(la.l2_psm);

		/* PSM must be odd and lsb of upper byte must be 0 */
		if ((psm & 0x0101) != 0x0001) {
			err = -EINVAL;
			goto done;
		}

		/* Restrict usage of well-known PSMs */
		if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) {
			err = -EACCES;
			goto done;
		}
	}

	write_lock_bh(&l2cap_sk_list.lock);

	if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) {
		err = -EADDRINUSE;
	} else {
		/* Save source address */
		bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
		l2cap_pi(sk)->psm   = la.l2_psm;
		l2cap_pi(sk)->sport = la.l2_psm;
		sk->sk_state = BT_BOUND;

		if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
					__le16_to_cpu(la.l2_psm) == 0x0003)
			l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
	}

	if (la.l2_cid)
		l2cap_pi(sk)->scid = la.l2_cid;

	write_unlock_bh(&l2cap_sk_list.lock);

done:
	release_sock(sk);
	return err;
}
Exemplo n.º 22
0
static void fib6_walker_unlink(struct fib6_walker *w)
{
	write_lock_bh(&fib6_walker_lock);
	list_del(&w->lh);
	write_unlock_bh(&fib6_walker_lock);
}
Exemplo n.º 23
0
static void fib6_walker_link(struct fib6_walker *w)
{
	write_lock_bh(&fib6_walker_lock);
	list_add(&w->lh, &fib6_walkers);
	write_unlock_bh(&fib6_walker_lock);
}
static int vif_add(struct vifctl *vifc, int mrtsock)
{
	int vifi = vifc->vifc_vifi;
	struct vif_device *v = &vif_table[vifi];
	struct net_device *dev;
	struct in_device *in_dev;

	/* Is vif busy ? */
	if (VIF_EXISTS(vifi))
		return -EADDRINUSE;

	switch (vifc->vifc_flags) {
#ifdef CONFIG_IP_PIMSM
	case VIFF_REGISTER:
		/*
		 * Special Purpose VIF in PIM
		 * All the packets will be sent to the daemon
		 */
		if (reg_vif_num >= 0)
			return -EADDRINUSE;
		dev = ipmr_reg_vif();
		if (!dev)
			return -ENOBUFS;
		break;
#endif
	case VIFF_TUNNEL:	
		dev = ipmr_new_tunnel(vifc);
		if (!dev)
			return -ENOBUFS;
		break;
	case 0:
		dev=ip_dev_find(vifc->vifc_lcl_addr.s_addr);
		if (!dev)
			return -EADDRNOTAVAIL;
		__dev_put(dev);
		break;
	default:
		return -EINVAL;
	}

	if ((in_dev = __in_dev_get_rtnl(dev)) == NULL)
		return -EADDRNOTAVAIL;
	in_dev->cnf.mc_forwarding++;
	dev_set_allmulti(dev, +1);
	ip_rt_multicast_event(in_dev);

	/*
	 *	Fill in the VIF structures
	 */
	v->rate_limit=vifc->vifc_rate_limit;
	v->local=vifc->vifc_lcl_addr.s_addr;
	v->remote=vifc->vifc_rmt_addr.s_addr;
	v->flags=vifc->vifc_flags;
	if (!mrtsock)
		v->flags |= VIFF_STATIC;
	v->threshold=vifc->vifc_threshold;
	v->bytes_in = 0;
	v->bytes_out = 0;
	v->pkt_in = 0;
	v->pkt_out = 0;
	v->link = dev->ifindex;
	if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER))
		v->link = dev->iflink;

	/* And finish update writing critical data */
	write_lock_bh(&mrt_lock);
	dev_hold(dev);
	v->dev=dev;
#ifdef CONFIG_IP_PIMSM
	if (v->flags&VIFF_REGISTER)
		reg_vif_num = vifi;
#endif
	if (vifi+1 > maxvif)
		maxvif = vifi+1;
	write_unlock_bh(&mrt_lock);
	return 0;
}
Exemplo n.º 25
0
static struct rt6_info *rt6_flow_lookup(struct rt6_info *rt,
					struct in6_addr *daddr,
					struct in6_addr *saddr,
					struct fl_acc_args *args)
{
	struct flow_rule *frule;
	struct rt6_info *nrt = NULL;
	struct pol_chain *pol;

	for (pol = rt6_pol_list; pol; pol = pol->next) {
		struct fib6_node *fn;
		struct rt6_info *sprt;

		fn = fib6_lookup(pol->rules, daddr, saddr);

		do {
			for (sprt = fn->leaf; sprt; sprt=sprt->u.next) {
				int res;

				frule = sprt->rt6i_flowr;
#if RT6_DEBUG >= 2
				if (frule == NULL) {
					printk(KERN_DEBUG "NULL flowr\n");
					goto error;
				}
#endif
				res = frule->ops->accept(rt, sprt, args, &nrt);

				switch (res) {
				case FLOWR_SELECT:
					goto found;
				case FLOWR_CLEAR:
					goto next_policy;
				case FLOWR_NODECISION:
					break;
				default:
					goto error;
				};
			}

			fn = fn->parent;

		} while ((fn->fn_flags & RTN_TL_ROOT) == 0);

	next_policy:
	}

error:
	dst_hold(&ip6_null_entry.u.dst);
	return &ip6_null_entry;

found:
	if (nrt == NULL)
		goto error;

	nrt->rt6i_flags |= RTF_CACHE;
	dst_hold(&nrt->u.dst);
	err = rt6_ins(nrt, NULL);
	if (err)
		nrt->u.dst.error = err;
	return nrt;
}
#endif

static int fib6_ifdown(struct rt6_info *rt, void *arg)
{
	if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
	    rt != &ip6_null_entry) {
		RT6_TRACE("deleted by ifdown %p\n", rt);
		return -1;
	}
	return 0;
}

void rt6_ifdown(struct net_device *dev)
{
	write_lock_bh(&rt6_lock);
	fib6_clean_tree(&ip6_routing_table, fib6_ifdown, 0, dev);
	write_unlock_bh(&rt6_lock);
}
Exemplo n.º 26
0
struct tcf_police * tcf_police_locate(struct rtattr *rta, struct rtattr *est)
{
	unsigned h;
	struct tcf_police *p;
	struct rtattr *tb[TCA_POLICE_MAX];
	struct tc_police *parm;

	if (rtattr_parse(tb, TCA_POLICE_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)) < 0)
		return NULL;

	if (tb[TCA_POLICE_TBF-1] == NULL)
		return NULL;

	parm = RTA_DATA(tb[TCA_POLICE_TBF-1]);

	if (parm->index && (p = tcf_police_lookup(parm->index)) != NULL) {
		p->refcnt++;
		return p;
	}

	p = kmalloc(sizeof(*p), GFP_KERNEL);
	if (p == NULL)
		return NULL;

	memset(p, 0, sizeof(*p));
	p->refcnt = 1;
	spin_lock_init(&p->lock);
	p->stats.lock = &p->lock;
	if (parm->rate.rate) {
		if ((p->R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE-1])) == NULL)
			goto failure;
		if (parm->peakrate.rate &&
		    (p->P_tab = qdisc_get_rtab(&parm->peakrate, tb[TCA_POLICE_PEAKRATE-1])) == NULL)
			goto failure;
	}
	if (tb[TCA_POLICE_RESULT-1])
		p->result = *(int*)RTA_DATA(tb[TCA_POLICE_RESULT-1]);
#ifdef CONFIG_NET_ESTIMATOR
	if (tb[TCA_POLICE_AVRATE-1])
		p->ewma_rate = *(u32*)RTA_DATA(tb[TCA_POLICE_AVRATE-1]);
#endif
	p->toks = p->burst = parm->burst;
	p->mtu = parm->mtu;
	if (p->mtu == 0) {
		p->mtu = ~0;
		if (p->R_tab)
			p->mtu = 255<<p->R_tab->rate.cell_log;
	}
	if (p->P_tab)
		p->ptoks = L2T_P(p, p->mtu);
	PSCHED_GET_TIME(p->t_c);
	p->index = parm->index ? : tcf_police_new_index();
	p->action = parm->action;
#ifdef CONFIG_NET_ESTIMATOR
	if (est)
		qdisc_new_estimator(&p->stats, est);
#endif
	h = tcf_police_hash(p->index);
	write_lock_bh(&police_lock);
	p->next = tcf_police_ht[h];
	tcf_police_ht[h] = p;
	write_unlock_bh(&police_lock);
	return p;

failure:
	if (p->R_tab)
		qdisc_put_rtab(p->R_tab);
	kfree(p);
	return NULL;
}
Exemplo n.º 27
0
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
{
	int uninitialized_var(err);
	struct net *net = sock_net(sk);
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct in6_flowlabel_req freq;
	struct ipv6_fl_socklist *sfl1=NULL;
	struct ipv6_fl_socklist *sfl, **sflp;
	struct ip6_flowlabel *fl, *fl1 = NULL;


	if (optlen < sizeof(freq))
		return -EINVAL;

	if (copy_from_user(&freq, optval, sizeof(freq)))
		return -EFAULT;

	switch (freq.flr_action) {
	case IPV6_FL_A_PUT:
		write_lock_bh(&ip6_sk_fl_lock);
		for (sflp = &np->ipv6_fl_list; (sfl=*sflp)!=NULL; sflp = &sfl->next) {
			if (sfl->fl->label == freq.flr_label) {
				if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK))
					np->flow_label &= ~IPV6_FLOWLABEL_MASK;
				*sflp = sfl->next;
				write_unlock_bh(&ip6_sk_fl_lock);
				fl_release(sfl->fl);
				kfree(sfl);
				return 0;
			}
		}
		write_unlock_bh(&ip6_sk_fl_lock);
		return -ESRCH;

	case IPV6_FL_A_RENEW:
		read_lock_bh(&ip6_sk_fl_lock);
		for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
			if (sfl->fl->label == freq.flr_label) {
				err = fl6_renew(sfl->fl, freq.flr_linger, freq.flr_expires);
				read_unlock_bh(&ip6_sk_fl_lock);
				return err;
			}
		}
		read_unlock_bh(&ip6_sk_fl_lock);

		if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
			fl = fl_lookup(net, freq.flr_label);
			if (fl) {
				err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
				fl_release(fl);
				return err;
			}
		}
		return -ESRCH;

	case IPV6_FL_A_GET:
		if (freq.flr_label & ~IPV6_FLOWLABEL_MASK)
			return -EINVAL;

		fl = fl_create(net, sk, &freq, optval, optlen, &err);
		if (fl == NULL)
			return err;
		sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL);

		if (freq.flr_label) {
			err = -EEXIST;
			read_lock_bh(&ip6_sk_fl_lock);
			for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) {
				if (sfl->fl->label == freq.flr_label) {
					if (freq.flr_flags&IPV6_FL_F_EXCL) {
						read_unlock_bh(&ip6_sk_fl_lock);
						goto done;
					}
					fl1 = sfl->fl;
					atomic_inc(&fl1->users);
					break;
				}
			}
			read_unlock_bh(&ip6_sk_fl_lock);

			if (fl1 == NULL)
				fl1 = fl_lookup(net, freq.flr_label);
			if (fl1) {
recheck:
				err = -EEXIST;
				if (freq.flr_flags&IPV6_FL_F_EXCL)
					goto release;
				err = -EPERM;
				if (fl1->share == IPV6_FL_S_EXCL ||
				    fl1->share != fl->share ||
				    fl1->owner != fl->owner)
					goto release;

				err = -EINVAL;
				if (!ipv6_addr_equal(&fl1->dst, &fl->dst) ||
				    ipv6_opt_cmp(fl1->opt, fl->opt))
					goto release;

				err = -ENOMEM;
				if (sfl1 == NULL)
					goto release;
				if (fl->linger > fl1->linger)
					fl1->linger = fl->linger;
				if ((long)(fl->expires - fl1->expires) > 0)
					fl1->expires = fl->expires;
				fl_link(np, sfl1, fl1);
				fl_free(fl);
				return 0;

release:
				fl_release(fl1);
				goto done;
			}
		}
		err = -ENOENT;
		if (!(freq.flr_flags&IPV6_FL_F_CREATE))
			goto done;

		err = -ENOMEM;
		if (sfl1 == NULL || (err = mem_check(sk)) != 0)
			goto done;

		fl1 = fl_intern(net, fl, freq.flr_label);
		if (fl1 != NULL)
			goto recheck;

		if (!freq.flr_label) {
			if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
					 &fl->label, sizeof(fl->label))) {
				/* Intentionally ignore fault. */
			}
		}

		fl_link(np, sfl1, fl);
		return 0;

	default:
		return -EINVAL;
	}

done:
	fl_free(fl);
	kfree(sfl1);
	return err;
}
Exemplo n.º 28
0
/*
 * Create a raw connection on a network device
 */
static void *privCreateRaw(char *pDevLabel)
{
  raw_socket *pRaw = NULL;
  int rvalue;
  struct net_device *pDev = NULL;

  if (NULL != pDevLabel) {
    pRaw = kmalloc(sizeof(raw_socket), GFP_ATOMIC);

    if (NULL != pRaw) {
      pRaw->pSocket = NULL;
      pRaw->bConnected = false;

      /* Create our socket */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0))
      rvalue = sock_create_kern(PF_PACKET,
                                SOCK_RAW,
                                htons(ETH_P_ALL),
                                &pRaw->pSocket);
#else
      rvalue = sock_create_lite(PF_PACKET,
                                SOCK_RAW,
                                htons(ETH_P_ALL),
                                &pRaw->pSocket);
#endif
      if ((rvalue >= 0) && (NULL != pRaw->pSocket)) {
        /* Need to reference our data structure */
        pRaw->pSocket->sk->sk_user_data = (void *)pRaw;

        /* Set 4 second timeout. Easy calculation. */
        pRaw->pSocket->sk->sk_sndtimeo = HZ << 2;
        pRaw->pSocket->sk->sk_rcvtimeo = HZ << 2;

        /* Yea, we can reuse this socket.  Needed? */
        pRaw->pSocket->sk->sk_reuse = 1;

        /* atomic allocation */
        pRaw->pSocket->sk->sk_allocation = GFP_ATOMIC;

        /* Create recv queue, before setting callbacks */
        init_waitqueue_head(&pRaw->recvQueue);

        /* We need a semaphore. */
        sema_init(&pRaw->sendWait, 1);

        /* Halt any callback */
        write_lock_bh(&pRaw->pSocket->sk->sk_callback_lock);

        /* Perhaps not needed, but remember our orignal data ready function. */
        pRaw->recvReady = pRaw->pSocket->sk->sk_data_ready;

        /* Our callback recv function. */
        pRaw->pSocket->sk->sk_data_ready = privRecvReady;

        /* Copy the header information */
        strncpy(pRaw->hdr.str, KLEM_NAME, 4);

        /* Set the protocol type */
        pRaw->uProtocol = KLEM_PROTOCOL;

        /* Set the protcol version */
        pRaw->uVersion = KLEM_INT_VERSION;

        /* Resume any callbacks */
        write_unlock_bh(&pRaw->pSocket->sk->sk_callback_lock);

        /* Find the device were will transmit the raw packet. */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,2,0))
        pDev = __dev_get_by_name(pRaw->pSocket->sk->__sk_common.skc_net,
                                 pDevLabel);
#else
        pDev = __dev_get_by_name(pRaw->pSocket->sk->__sk_common.skc_net.net,
                                 pDevLabel);
#endif
        if (NULL != pDev) {
          memcpy(pRaw->pDevMac, (char *)pDev->perm_addr, ETH_ALEN);
        } else {
          /* We failed, broadcasting it might work, lets try that. */
          KLEM_MSG("Didn't find network device, we will broadcast it");
          memset(pRaw->pDevMac, 0xff, ETH_ALEN);
        }

        /* Default the lemu to broadcast. */
        memset(pRaw->pLemuMac, 0xff, ETH_ALEN);

        /* Set the send/recv threads to null */
        pRaw->pRecvThread = NULL;

        /* Lets say we have a conenction now. */
        pRaw->bConnected = true;
      } else {
        KLEM_LOG("Error creating socket %s %d\n", pDevLabel, rvalue);
        kfree(pRaw);
        pRaw = NULL;
      }
    }
  }

  return pRaw;
}
Exemplo n.º 29
0
int rst_restore_netdev(struct cpt_context *ctx)
{
	struct net *net = get_exec_env()->ve_netns;
	int err;
	loff_t sec = ctx->sections[CPT_SECT_NET_DEVICE];
	loff_t endsec;
	struct cpt_section_hdr h;
	struct cpt_netdev_image di;
	struct net_device *dev;

	get_exec_env()->disable_net = 1;

	if (sec == CPT_NULL)
		return 0;

	err = ctx->pread(&h, sizeof(h), ctx, sec);
	if (err)
		return err;
	if (h.cpt_section != CPT_SECT_NET_DEVICE || h.cpt_hdrlen < sizeof(h))
		return -EINVAL;

	endsec = sec + h.cpt_next;
	sec += h.cpt_hdrlen;
	while (sec < endsec) {
		loff_t pos;
		struct net_device *dev_new;
		struct netdev_rst *ops;

		err = rst_get_object(CPT_OBJ_NET_DEVICE, sec, &di, ctx);
		if (err)
			return err;

		rtnl_lock();
		pos = sec + di.cpt_hdrlen;
		if (di.cpt_next > sizeof(di)) {
			struct cpt_object_hdr hdr;
			err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
					ctx, sec + di.cpt_hdrlen);
			if (err)
				goto out;

			ops = NULL;
			while (1) {
				ops = netdev_find_rst(hdr.cpt_object, ops);
				if (ops == NULL)
					break;

				err = ops->ndo_rst(sec, &di, &rst_ops, ctx);
				if (!err) {
					pos += hdr.cpt_next;
					break;
				} else if (err < 0) {
					eprintk_ctx("netdev %d rst failed %d\n",
							hdr.cpt_object, err);
					goto out;
				}
			}
		}

		dev = __dev_get_by_name(net, di.cpt_name);
		if (dev) {
			if (dev->ifindex != di.cpt_index) {
				dev_new = __dev_get_by_index(net, di.cpt_index);
				if (!dev_new) {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					write_unlock_bh(&dev_base_lock);
				} else {
					write_lock_bh(&dev_base_lock);
					hlist_del(&dev->index_hlist);
					hlist_del(&dev_new->index_hlist);
					if (dev_new->iflink == dev_new->ifindex)
						dev_new->iflink = dev->ifindex;
					dev_new->ifindex = dev->ifindex;
					if (dev->iflink == dev->ifindex)
						dev->iflink = di.cpt_index;
					dev->ifindex = di.cpt_index;
					hlist_add_head(&dev->index_hlist,
							dev_index_hash(net, dev->ifindex));
					hlist_add_head(&dev_new->index_hlist,
							dev_index_hash(net, dev_new->ifindex));
					write_unlock_bh(&dev_base_lock);
				}
			}
			if (di.cpt_flags^dev->flags) {
				err = dev_change_flags(dev, di.cpt_flags);
				if (err)
					eprintk_ctx("dev_change_flags err: %d\n", err);
			}
			while (pos < sec + di.cpt_next) {
				struct cpt_object_hdr hdr;
				err = ctx->pread(&hdr, sizeof(struct cpt_object_hdr),
						ctx, pos);
				if (err)
					goto out;
				if (hdr.cpt_object == CPT_OBJ_NET_HWADDR) {
					/* Restore hardware address */
					struct cpt_hwaddr_image hw;
					err = rst_get_object(CPT_OBJ_NET_HWADDR,
							pos, &hw, ctx);
					if (err)
						goto out;
					BUILD_BUG_ON(sizeof(hw.cpt_dev_addr) !=
							MAX_ADDR_LEN);
					memcpy(dev->dev_addr, hw.cpt_dev_addr,
							sizeof(hw.cpt_dev_addr));
				} else if (hdr.cpt_object == CPT_OBJ_NET_STATS) {
					err = rst_restore_netstats(pos, dev, ctx);
					if (err) {
						eprintk_ctx("rst stats %s: %d\n",
								di.cpt_name, err);
						goto out;
					}
				}
				pos += hdr.cpt_next;
			}
		} else {
			eprintk_ctx("unknown interface 2 %s\n", di.cpt_name);
		}
		rtnl_unlock();
		sec += di.cpt_next;
	}
	return 0;
out:
	rtnl_unlock();
	return err;
}
Exemplo n.º 30
0
inline void brk_list_write_lock(void) {
	write_lock_bh(&brk_list_lock);
}