extern int can_proto_register(const struct can_proto *cp);
extern void can_proto_unregister(const struct can_proto *cp);
extern int can_proto_register(const struct can_proto *cp);
extern void can_proto_unregister(const struct can_proto *cp);
-extern int can_rx_register(struct net_device *dev, canid_t can_id,
- canid_t mask,
- void (*func)(struct sk_buff *, void *),
- void *data, char *ident);
+int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
+ void (*func)(struct sk_buff *, void *),
+ void *data, char *ident, struct sock *sk);
extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
canid_t mask,
extern void can_rx_unregister(struct net_device *dev, canid_t can_id,
canid_t mask,
* @func: callback function on filter match
* @data: returned parameter for callback function
* @ident: string for calling module indentification
* @func: callback function on filter match
* @data: returned parameter for callback function
* @ident: string for calling module indentification
+ * @sk: socket pointer (might be NULL)
*
* Description:
* Invokes the callback function with the received sk_buff and the given
*
* Description:
* Invokes the callback function with the received sk_buff and the given
*/
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
void (*func)(struct sk_buff *, void *), void *data,
*/
int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask,
void (*func)(struct sk_buff *, void *), void *data,
+ char *ident, struct sock *sk)
{
struct receiver *r;
struct hlist_head *rl;
{
struct receiver *r;
struct hlist_head *rl;
r->func = func;
r->data = data;
r->ident = ident;
r->func = func;
r->data = data;
r->ident = ident;
hlist_add_head_rcu(&r->list, rl);
d->entries++;
hlist_add_head_rcu(&r->list, rl);
d->entries++;
static void can_rx_delete_receiver(struct rcu_head *rp)
{
struct receiver *r = container_of(rp, struct receiver, rcu);
static void can_rx_delete_receiver(struct rcu_head *rp)
{
struct receiver *r = container_of(rp, struct receiver, rcu);
+ struct sock *sk = r->sk;
kmem_cache_free(rcv_cache, r);
kmem_cache_free(rcv_cache, r);
+ if (sk)
+ sock_put(sk);
spin_unlock(&can_rcvlists_lock);
/* schedule the receiver item for deletion */
spin_unlock(&can_rcvlists_lock);
/* schedule the receiver item for deletion */
+ if (r) {
+ if (r->sk)
+ sock_hold(r->sk);
call_rcu(&r->rcu, can_rx_delete_receiver);
call_rcu(&r->rcu, can_rx_delete_receiver);
}
EXPORT_SYMBOL(can_rx_unregister);
}
EXPORT_SYMBOL(can_rx_unregister);
struct receiver {
struct hlist_node list;
struct receiver {
struct hlist_node list;
canid_t can_id;
canid_t mask;
unsigned long matches;
void (*func)(struct sk_buff *, void *);
void *data;
char *ident;
canid_t can_id;
canid_t mask;
unsigned long matches;
void (*func)(struct sk_buff *, void *);
void *data;
char *ident;
+ struct sock *sk;
+ struct rcu_head rcu;
};
enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
};
enum { RX_ERR, RX_ALL, RX_FIL, RX_INV, RX_EFF, RX_MAX };
err = can_rx_register(dev, op->can_id,
REGMASK(op->can_id),
bcm_rx_handler, op,
err = can_rx_register(dev, op->can_id,
REGMASK(op->can_id),
bcm_rx_handler, op,
op->rx_reg_dev = dev;
dev_put(dev);
op->rx_reg_dev = dev;
dev_put(dev);
} else
err = can_rx_register(NULL, op->can_id,
REGMASK(op->can_id),
} else
err = can_rx_register(NULL, op->can_id,
REGMASK(op->can_id),
- bcm_rx_handler, op, "bcm");
+ bcm_rx_handler, op, "bcm", sk);
if (err) {
/* this bcm rx op is broken -> remove it */
list_del(&op->list);
if (err) {
/* this bcm rx op is broken -> remove it */
list_del(&op->list);
{
return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
gwj->ccgw.filter.can_mask, can_can_gw_rcv,
{
return can_rx_register(gwj->src.dev, gwj->ccgw.filter.can_id,
gwj->ccgw.filter.can_mask, can_can_gw_rcv,
}
static inline void cgw_unregister_filter(struct cgw_job *gwj)
}
static inline void cgw_unregister_filter(struct cgw_job *gwj)
for (i = 0; i < count; i++) {
err = can_rx_register(dev, filter[i].can_id,
filter[i].can_mask,
for (i = 0; i < count; i++) {
err = can_rx_register(dev, filter[i].can_id,
filter[i].can_mask,
+ raw_rcv, sk, "raw", sk);
if (err) {
/* clean up successfully registered filters */
while (--i >= 0)
if (err) {
/* clean up successfully registered filters */
while (--i >= 0)
if (err_mask)
err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
if (err_mask)
err = can_rx_register(dev, 0, err_mask | CAN_ERR_FLAG,
+ raw_rcv, sk, "raw", sk);