diff options
Diffstat (limited to 'net/irda')
-rw-r--r-- | net/irda/Makefile | 2 | ||||
-rw-r--r-- | net/irda/discovery.c | 2 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_core.c | 2 | ||||
-rw-r--r-- | net/irda/iriap.c | 2 | ||||
-rw-r--r-- | net/irda/irlan/irlan_common.c | 2 | ||||
-rw-r--r-- | net/irda/irlap.c | 2 | ||||
-rw-r--r-- | net/irda/irlap_event.c | 28 | ||||
-rw-r--r-- | net/irda/irlap_frame.c | 10 | ||||
-rw-r--r-- | net/irda/irlmp.c | 2 | ||||
-rw-r--r-- | net/irda/irmod.c | 48 | ||||
-rw-r--r-- | net/irda/irnetlink.c | 170 | ||||
-rw-r--r-- | net/irda/irttp.c | 31 |
12 files changed, 255 insertions, 46 deletions
diff --git a/net/irda/Makefile b/net/irda/Makefile index d1366c2a39c..187f6c563a4 100644 --- a/net/irda/Makefile +++ b/net/irda/Makefile @@ -10,6 +10,6 @@ obj-$(CONFIG_IRCOMM) += ircomm/ irda-y := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ irttp.o irda_device.o irias_object.o wrapper.o af_irda.o \ - discovery.o parameters.o irmod.o + discovery.o parameters.o irnetlink.o irmod.o irda-$(CONFIG_PROC_FS) += irproc.o irda-$(CONFIG_SYSCTL) += irsysctl.o diff --git a/net/irda/discovery.c b/net/irda/discovery.c index f0973412867..af0cea721d2 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c @@ -395,7 +395,7 @@ static int discovery_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations discovery_seq_ops = { +static const struct seq_operations discovery_seq_ops = { .start = discovery_seq_start, .next = discovery_seq_next, .stop = discovery_seq_stop, diff --git a/net/irda/ircomm/ircomm_core.c b/net/irda/ircomm/ircomm_core.c index 4749f8f5539..2d63fa8e155 100644 --- a/net/irda/ircomm/ircomm_core.c +++ b/net/irda/ircomm/ircomm_core.c @@ -562,7 +562,7 @@ static int ircomm_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations ircomm_seq_ops = { +static const struct seq_operations ircomm_seq_ops = { .start = ircomm_seq_start, .next = ircomm_seq_next, .stop = ircomm_seq_stop, diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 915d9384f36..774eb707940 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -1066,7 +1066,7 @@ static int irias_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations irias_seq_ops = { +static const struct seq_operations irias_seq_ops = { .start = irias_seq_start, .next = irias_seq_next, .stop = irias_seq_stop, diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index ed69773b0f8..f5778ef3ccc 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -1217,7 +1217,7 @@ static int irlan_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations irlan_seq_ops = { +static const struct seq_operations irlan_seq_ops = { .start = irlan_seq_start, .next = irlan_seq_next, .stop = irlan_seq_stop, diff --git a/net/irda/irlap.c b/net/irda/irlap.c index d93ebd11431..2fc9f518f89 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c @@ -1210,7 +1210,7 @@ static int irlap_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations irlap_seq_ops = { +static const struct seq_operations irlap_seq_ops = { .start = irlap_seq_start, .next = irlap_seq_next, .stop = irlap_seq_stop, diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index 0b02073ffdf..a8b8873aa26 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -317,23 +317,6 @@ void irlap_do_event(struct irlap_cb *self, IRLAP_EVENT event, } /* - * Function irlap_next_state (self, state) - * - * Switches state and provides debug information - * - */ -static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) -{ - /* - if (!self || self->magic != LAP_MAGIC) - return; - - IRDA_DEBUG(4, "next LAP state = %s\n", irlap_state[state]); - */ - self->state = state; -} - -/* * Function irlap_state_ndm (event, skb, frame) * * NDM (Normal Disconnected Mode) state @@ -1086,7 +1069,6 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, } else { /* Final packet of window */ irlap_send_data_primary_poll(self, skb); - irlap_next_state(self, LAP_NRM_P); /* * Make sure state machine does not try to send @@ -1436,14 +1418,14 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, */ self->remote_busy = FALSE; + /* Stop final timer */ + del_timer(&self->final_timer); + /* * Nr as expected? */ ret = irlap_validate_nr_received(self, info->nr); if (ret == NR_EXPECTED) { - /* Stop final timer */ - del_timer(&self->final_timer); - /* Update Nr received */ irlap_update_nr_received(self, info->nr); @@ -1475,14 +1457,12 @@ static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, /* Resend rejected frames */ irlap_resend_rejected_frames(self, CMD_FRAME); - - /* Final timer ??? Jean II */ + irlap_start_final_timer(self, self->final_timeout * 2); irlap_next_state(self, LAP_NRM_P); } else if (ret == NR_INVALID) { IRDA_DEBUG(1, "%s(), Received RR with " "invalid nr !\n", __FUNCTION__); - del_timer(&self->final_timer); irlap_next_state(self, LAP_RESET_WAIT); diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 3c5a68e3641..25a3444a923 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -101,6 +101,13 @@ void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb) irlap_insert_info(self, skb); + if (unlikely(self->mode & IRDA_MODE_MONITOR)) { + IRDA_DEBUG(3, "%s(): %s is in monitor mode\n", __FUNCTION__, + self->netdev->name); + dev_kfree_skb(skb); + return; + } + dev_queue_xmit(skb); } @@ -798,16 +805,19 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) self->vs = (self->vs + 1) % 8; self->ack_required = FALSE; + irlap_next_state(self, LAP_NRM_P); irlap_send_i_frame(self, tx_skb, CMD_FRAME); } else { IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__); if (self->ack_required) { irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); + irlap_next_state(self, LAP_NRM_P); irlap_send_rr_frame(self, CMD_FRAME); self->ack_required = FALSE; } else { skb->data[1] |= PF_BIT; + irlap_next_state(self, LAP_NRM_P); irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME); } } diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 9df0461b6d1..24a5e3f2377 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -1994,7 +1994,7 @@ static int irlmp_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations irlmp_seq_ops = { +static const struct seq_operations irlmp_seq_ops = { .start = irlmp_seq_start, .next = irlmp_seq_next, .stop = irlmp_seq_stop, diff --git a/net/irda/irmod.c b/net/irda/irmod.c index c7fad2c5b9f..1900937b332 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -88,16 +88,23 @@ EXPORT_SYMBOL(irda_notify_init); */ static int __init irda_init(void) { + int ret = 0; + IRDA_DEBUG(0, "%s()\n", __FUNCTION__); /* Lower layer of the stack */ irlmp_init(); irlap_init(); + /* Driver/dongle support */ + irda_device_init(); + /* Higher layers of the stack */ iriap_init(); irttp_init(); - irsock_init(); + ret = irsock_init(); + if (ret < 0) + goto out_err_1; /* Add IrDA packet type (Start receiving packets) */ dev_add_pack(&irda_packet_type); @@ -107,13 +114,44 @@ static int __init irda_init(void) irda_proc_register(); #endif #ifdef CONFIG_SYSCTL - irda_sysctl_register(); + ret = irda_sysctl_register(); + if (ret < 0) + goto out_err_2; #endif - /* Driver/dongle support */ - irda_device_init(); + ret = irda_nl_register(); + if (ret < 0) + goto out_err_3; return 0; + + out_err_3: +#ifdef CONFIG_SYSCTL + irda_sysctl_unregister(); +#endif + out_err_2: +#ifdef CONFIG_PROC_FS + irda_proc_unregister(); +#endif + + /* Remove IrDA packet type (stop receiving packets) */ + dev_remove_pack(&irda_packet_type); + + /* Remove higher layers */ + irsock_cleanup(); + out_err_1: + irttp_cleanup(); + iriap_cleanup(); + + /* Remove lower layers */ + irda_device_cleanup(); + irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */ + + /* Remove middle layer */ + irlmp_cleanup(); + + + return ret; } /* @@ -125,6 +163,8 @@ static int __init irda_init(void) static void __exit irda_cleanup(void) { /* Remove External APIs */ + irda_nl_unregister(); + #ifdef CONFIG_SYSCTL irda_sysctl_unregister(); #endif diff --git a/net/irda/irnetlink.c b/net/irda/irnetlink.c new file mode 100644 index 00000000000..db716580e1a --- /dev/null +++ b/net/irda/irnetlink.c @@ -0,0 +1,170 @@ +/* + * IrDA netlink layer, for stack configuration. + * + * Copyright (c) 2007 Samuel Ortiz <samuel@sortiz> + * + * Partly based on the 802.11 nelink implementation + * (see net/wireless/nl80211.c) which is: + * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/socket.h> +#include <linux/irda.h> +#include <net/sock.h> +#include <net/irda/irda.h> +#include <net/irda/irlap.h> +#include <net/genetlink.h> + + + +static struct genl_family irda_nl_family = { + .id = GENL_ID_GENERATE, + .name = IRDA_NL_NAME, + .hdrsize = 0, + .version = IRDA_NL_VERSION, + .maxattr = IRDA_NL_CMD_MAX, +}; + +static struct net_device * ifname_to_netdev(struct genl_info *info) +{ + char * ifname; + + if (!info->attrs[IRDA_NL_ATTR_IFNAME]) + return NULL; + + ifname = nla_data(info->attrs[IRDA_NL_ATTR_IFNAME]); + + IRDA_DEBUG(5, "%s(): Looking for %s\n", __FUNCTION__, ifname); + + return dev_get_by_name(ifname); +} + +static int irda_nl_set_mode(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device * dev; + struct irlap_cb * irlap; + u32 mode; + + if (!info->attrs[IRDA_NL_ATTR_MODE]) + return -EINVAL; + + mode = nla_get_u32(info->attrs[IRDA_NL_ATTR_MODE]); + + IRDA_DEBUG(5, "%s(): Switching to mode: %d\n", __FUNCTION__, mode); + + dev = ifname_to_netdev(info); + if (!dev) + return -ENODEV; + + irlap = (struct irlap_cb *)dev->atalk_ptr; + if (!irlap) { + dev_put(dev); + return -ENODEV; + } + + irlap->mode = mode; + + dev_put(dev); + + return 0; +} + +static int irda_nl_get_mode(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device * dev; + struct irlap_cb * irlap; + struct sk_buff *msg; + void *hdr; + int ret = -ENOBUFS; + + dev = ifname_to_netdev(info); + if (!dev) + return -ENODEV; + + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) { + dev_put(dev); + return -ENOMEM; + } + + irlap = (struct irlap_cb *)dev->atalk_ptr; + if (!irlap) { + ret = -ENODEV; + goto err_out; + } + + hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, + &irda_nl_family, 0, IRDA_NL_CMD_GET_MODE); + if (IS_ERR(hdr)) { + ret = PTR_ERR(hdr); + goto err_out; + } + + if(nla_put_string(msg, IRDA_NL_ATTR_IFNAME, + dev->name)); + goto err_out; + + if(nla_put_u32(msg, IRDA_NL_ATTR_MODE, irlap->mode)) + goto err_out; + + genlmsg_end(msg, hdr); + + return genlmsg_unicast(msg, info->snd_pid); + + err_out: + nlmsg_free(msg); + dev_put(dev); + + return ret; +} + +static struct nla_policy irda_nl_policy[IRDA_NL_ATTR_MAX + 1] = { + [IRDA_NL_ATTR_IFNAME] = { .type = NLA_NUL_STRING, + .len = IFNAMSIZ-1 }, + [IRDA_NL_ATTR_MODE] = { .type = NLA_U32 }, +}; + +static struct genl_ops irda_nl_ops[] = { + { + .cmd = IRDA_NL_CMD_SET_MODE, + .doit = irda_nl_set_mode, + .policy = irda_nl_policy, + .flags = GENL_ADMIN_PERM, + }, + { + .cmd = IRDA_NL_CMD_GET_MODE, + .doit = irda_nl_get_mode, + .policy = irda_nl_policy, + /* can be retrieved by unprivileged users */ + }, + +}; + +int irda_nl_register(void) +{ + int err, i; + + err = genl_register_family(&irda_nl_family); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(irda_nl_ops); i++) { + err = genl_register_ops(&irda_nl_family, &irda_nl_ops[i]); + if (err) + goto err_out; + } + return 0; + err_out: + genl_unregister_family(&irda_nl_family); + return err; +} + +void irda_nl_unregister(void) +{ + genl_unregister_family(&irda_nl_family); +} diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 7069e4a5825..7f50832a2cd 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -369,6 +369,20 @@ static int irttp_param_max_sdu_size(void *instance, irda_param_t *param, /* Everything is happily mixed up. Waiting for next clean up - Jean II */ /* + * Initialization, that has to be done on new tsap + * instance allocation and on duplication + */ +static void irttp_init_tsap(struct tsap_cb *tsap) +{ + spin_lock_init(&tsap->lock); + init_timer(&tsap->todo_timer); + + skb_queue_head_init(&tsap->rx_queue); + skb_queue_head_init(&tsap->tx_queue); + skb_queue_head_init(&tsap->rx_fragments); +} + +/* * Function irttp_open_tsap (stsap, notify) * * Create TSAP connection endpoint, @@ -395,10 +409,11 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) IRDA_DEBUG(0, "%s(), unable to kmalloc!\n", __FUNCTION__); return NULL; } - spin_lock_init(&self->lock); + + /* Initialize internal objects */ + irttp_init_tsap(self); /* Initialise todo timer */ - init_timer(&self->todo_timer); self->todo_timer.data = (unsigned long) self; self->todo_timer.function = &irttp_todo_expired; @@ -418,9 +433,6 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) self->magic = TTP_TSAP_MAGIC; self->connected = FALSE; - skb_queue_head_init(&self->rx_queue); - skb_queue_head_init(&self->tx_queue); - skb_queue_head_init(&self->rx_fragments); /* * Create LSAP at IrLMP layer */ @@ -1455,12 +1467,9 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) /* Not everything should be copied */ new->notify.instance = instance; - spin_lock_init(&new->lock); - init_timer(&new->todo_timer); - skb_queue_head_init(&new->rx_queue); - skb_queue_head_init(&new->tx_queue); - skb_queue_head_init(&new->rx_fragments); + /* Initialize internal objects */ + irttp_init_tsap(new); /* This is locked */ hashbin_insert(irttp->tsaps, (irda_queue_t *) new, (long) new, NULL); @@ -1866,7 +1875,7 @@ static int irttp_seq_show(struct seq_file *seq, void *v) return 0; } -static struct seq_operations irttp_seq_ops = { +static const struct seq_operations irttp_seq_ops = { .start = irttp_seq_start, .next = irttp_seq_next, .stop = irttp_seq_stop, |