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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
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); }
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); }
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); } } }
/** * 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); }
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); }
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; } } }
/* * 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; }
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; }
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; }
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); }
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; }
/** * 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 {
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; }
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); }
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; }
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); }
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; }
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; }
/* * 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; }
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; }
inline void brk_list_write_lock(void) { write_lock_bh(&brk_list_lock); }