Release 4.11 net/irda/af_irda.c
/*********************************************************************
*
* Filename: af_irda.c
* Version: 0.9
* Description: IrDA sockets implementation
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun May 31 10:12:43 1998
* Modified at: Sat Dec 25 21:10:23 1999
* Modified by: Dag Brattli <dag@brattli.net>
* Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
*
* Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1999-2003 Jean Tourrilhes <jt@hpl.hp.com>
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Linux-IrDA now supports four different types of IrDA sockets:
*
* o SOCK_STREAM: TinyTP connections with SAR disabled. The
* max SDU size is 0 for conn. of this type
* o SOCK_SEQPACKET: TinyTP connections with SAR enabled. TTP may
* fragment the messages, but will preserve
* the message boundaries
* o SOCK_DGRAM: IRDAPROTO_UNITDATA: TinyTP connections with Unitdata
* (unreliable) transfers
* IRDAPROTO_ULTRA: Connectionless and unreliable data
*
********************************************************************/
#include <linux/capability.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/slab.h>
#include <linux/sched/signal.h>
#include <linux/init.h>
#include <linux/net.h>
#include <linux/irda.h>
#include <linux/poll.h>
#include <asm/ioctls.h> /* TIOCOUTQ, TIOCINQ */
#include <linux/uaccess.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/irda/af_irda.h>
static int irda_create(struct net *net, struct socket *sock, int protocol, int kern);
static const struct proto_ops irda_stream_ops;
static const struct proto_ops irda_seqpacket_ops;
static const struct proto_ops irda_dgram_ops;
#ifdef CONFIG_IRDA_ULTRA
static const struct proto_ops irda_ultra_ops;
#define ULTRA_MAX_DATA 382
#endif /* CONFIG_IRDA_ULTRA */
#define IRDA_MAX_HEADER (TTP_MAX_HEADER)
/*
* Function irda_data_indication (instance, sap, skb)
*
* Received some data from TinyTP. Just queue it on the receive queue
*
*/
static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb)
{
struct irda_sock *self;
struct sock *sk;
int err;
self = instance;
sk = instance;
err = sock_queue_rcv_skb(sk, skb);
if (err) {
pr_debug("%s(), error: no more mem!\n", __func__);
self->rx_flow = FLOW_STOP;
/* When we return error, TTP will need to requeue the skb */
return err;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 70 | 93.33% | 2 | 33.33% |
Jean Tourrilhes | 2 | 2.67% | 1 | 16.67% |
Joe Perches | 1 | 1.33% | 1 | 16.67% |
Arnaldo Carvalho de Melo | 1 | 1.33% | 1 | 16.67% |
Harvey Harrison | 1 | 1.33% | 1 | 16.67% |
Total | 75 | 100.00% | 6 | 100.00% |
/*
* Function irda_disconnect_indication (instance, sap, reason, skb)
*
* Connection has been closed. Check reason to find out why
*
*/
static void irda_disconnect_indication(void *instance, void *sap,
LM_REASON reason, struct sk_buff *skb)
{
struct irda_sock *self;
struct sock *sk;
self = instance;
pr_debug("%s(%p)\n", __func__, self);
/* Don't care about it, but let's not leak it */
if(skb)
dev_kfree_skb(skb);
sk = instance;
if (sk == NULL) {
pr_debug("%s(%p) : BUG : sk is NULL\n",
__func__, self);
return;
}
/* Prevent race conditions with irda_release() and irda_shutdown() */
bh_lock_sock(sk);
if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
/* Close our TSAP.
* If we leave it open, IrLMP put it back into the list of
* unconnected LSAPs. The problem is that any incoming request
* can then be matched to this socket (and it will be, because
* it is at the head of the list). This would prevent any
* listening socket waiting on the same TSAP to get those
* requests. Some apps forget to close sockets, or hang to it
* a bit too long, so we may stay in this dead state long
* enough to be noticed...
* Note : all socket function do check sk->sk_state, so we are
* safe...
* Jean II
*/
if (self->tsap) {
irttp_close_tsap(self->tsap);
self->tsap = NULL;
}
}
bh_unlock_sock(sk);
/* Note : once we are there, there is not much you want to do
* with the socket anymore, apart from closing it.
* For example, bind() and connect() won't reset sk->sk_err,
* sk->sk_shutdown and sk->sk_flags to valid values...
* Jean II
*/
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 75 | 50.68% | 4 | 26.67% |
Linus Torvalds | 36 | 24.32% | 2 | 13.33% |
Jean Tourrilhes | 11 | 7.43% | 2 | 13.33% |
Arnaldo Carvalho de Melo | 10 | 6.76% | 3 | 20.00% |
Olaf Kirch | 10 | 6.76% | 1 | 6.67% |
Harvey Harrison | 2 | 1.35% | 1 | 6.67% |
Joe Perches | 2 | 1.35% | 1 | 6.67% |
James Morris | 2 | 1.35% | 1 | 6.67% |
Total | 148 | 100.00% | 15 | 100.00% |
/*
* Function irda_connect_confirm (instance, sap, qos, max_sdu_size, skb)
*
* Connections has been confirmed by the remote device
*
*/
static void irda_connect_confirm(void *instance, void *sap,
struct qos_info *qos,
__u32 max_sdu_size, __u8 max_header_size,
struct sk_buff *skb)
{
struct irda_sock *self;
struct sock *sk;
self = instance;
pr_debug("%s(%p)\n", __func__, self);
sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
}
dev_kfree_skb(skb);
// Should be ??? skb_queue_tail(&sk->sk_receive_queue, skb);
/* How much header space do we need to reserve */
self->max_header_size = max_header_size;
/* IrTTP max SDU size in transmit direction */
self->max_sdu_size_tx = max_sdu_size;
/* Find out what the largest chunk of data that we can transmit is */
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
net_err_ratelimited("%s: max_sdu_size must be 0\n",
__func__);
return;
}
self->max_data_size = irttp_get_max_seg_size(self->tsap);
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
net_err_ratelimited("%s: max_sdu_size cannot be 0\n",
__func__);
return;
}
self->max_data_size = max_sdu_size;
break;
default:
self->max_data_size = irttp_get_max_seg_size(self->tsap);
}
pr_debug("%s(), max_data_size=%d\n", __func__,
self->max_data_size);
memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
/* We are now connected! */
sk->sk_state = TCP_ESTABLISHED;
sk->sk_state_change(sk);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 172 | 81.90% | 6 | 37.50% |
Jean Tourrilhes | 16 | 7.62% | 3 | 18.75% |
Linus Torvalds | 5 | 2.38% | 1 | 6.25% |
Arnaldo Carvalho de Melo | 5 | 2.38% | 2 | 12.50% |
Joe Perches | 4 | 1.90% | 2 | 12.50% |
Martin Dalecki | 4 | 1.90% | 1 | 6.25% |
Harvey Harrison | 4 | 1.90% | 1 | 6.25% |
Total | 210 | 100.00% | 16 | 100.00% |
/*
* Function irda_connect_indication(instance, sap, qos, max_sdu_size, userdata)
*
* Incoming connection
*
*/
static void irda_connect_indication(void *instance, void *sap,
struct qos_info *qos, __u32 max_sdu_size,
__u8 max_header_size, struct sk_buff *skb)
{
struct irda_sock *self;
struct sock *sk;
self = instance;
pr_debug("%s(%p)\n", __func__, self);
sk = instance;
if (sk == NULL) {
dev_kfree_skb(skb);
return;
}
/* How much header space do we need to reserve */
self->max_header_size = max_header_size;
/* IrTTP max SDU size in transmit direction */
self->max_sdu_size_tx = max_sdu_size;
/* Find out what the largest chunk of data that we can transmit is */
switch (sk->sk_type) {
case SOCK_STREAM:
if (max_sdu_size != 0) {
net_err_ratelimited("%s: max_sdu_size must be 0\n",
__func__);
kfree_skb(skb);
return;
}
self->max_data_size = irttp_get_max_seg_size(self->tsap);
break;
case SOCK_SEQPACKET:
if (max_sdu_size == 0) {
net_err_ratelimited("%s: max_sdu_size cannot be 0\n",
__func__);
kfree_skb(skb);
return;
}
self->max_data_size = max_sdu_size;
break;
default:
self->max_data_size = irttp_get_max_seg_size(self->tsap);
}
pr_debug("%s(), max_data_size=%d\n", __func__,
self->max_data_size);
memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_state_change(sk);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 175 | 80.65% | 6 | 37.50% |
Jean Tourrilhes | 21 | 9.68% | 3 | 18.75% |
Linus Torvalds | 5 | 2.30% | 1 | 6.25% |
Harvey Harrison | 4 | 1.84% | 1 | 6.25% |
Arnaldo Carvalho de Melo | 4 | 1.84% | 2 | 12.50% |
Joe Perches | 4 | 1.84% | 2 | 12.50% |
Martin Dalecki | 4 | 1.84% | 1 | 6.25% |
Total | 217 | 100.00% | 16 | 100.00% |
/*
* Function irda_connect_response (handle)
*
* Accept incoming connection
*
*/
static void irda_connect_response(struct irda_sock *self)
{
struct sk_buff *skb;
skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER, GFP_KERNEL);
if (skb == NULL) {
pr_debug("%s() Unable to allocate sk_buff!\n",
__func__);
return;
}
/* Reserve space for MUX_CONTROL and LAP header */
skb_reserve(skb, IRDA_MAX_HEADER);
irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 53 | 82.81% | 4 | 36.36% |
Samuel Ortiz | 5 | 7.81% | 2 | 18.18% |
Jean Tourrilhes | 2 | 3.12% | 1 | 9.09% |
Adrian Bunk | 1 | 1.56% | 1 | 9.09% |
Joe Perches | 1 | 1.56% | 1 | 9.09% |
Mathias Krause | 1 | 1.56% | 1 | 9.09% |
Harvey Harrison | 1 | 1.56% | 1 | 9.09% |
Total | 64 | 100.00% | 11 | 100.00% |
/*
* Function irda_flow_indication (instance, sap, flow)
*
* Used by TinyTP to tell us if it can accept more data or not
*
*/
static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
{
struct irda_sock *self;
struct sock *sk;
self = instance;
sk = instance;
BUG_ON(sk == NULL);
switch (flow) {
case FLOW_STOP:
pr_debug("%s(), IrTTP wants us to slow down\n",
__func__);
self->tx_flow = flow;
break;
case FLOW_START:
self->tx_flow = flow;
pr_debug("%s(), IrTTP wants us to start again\n",
__func__);
wake_up_interruptible(sk_sleep(sk));
break;
default:
pr_debug("%s(), Unknown flow command!\n", __func__);
/* Unknown flow command, better stop */
self->tx_flow = flow;
break;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 84 | 79.25% | 3 | 30.00% |
Jean Tourrilhes | 6 | 5.66% | 1 | 10.00% |
Samuel Ortiz | 5 | 4.72% | 1 | 10.00% |
Eric Dumazet | 3 | 2.83% | 1 | 10.00% |
Harvey Harrison | 3 | 2.83% | 1 | 10.00% |
Joe Perches | 3 | 2.83% | 1 | 10.00% |
Arnaldo Carvalho de Melo | 2 | 1.89% | 2 | 20.00% |
Total | 106 | 100.00% | 10 | 100.00% |
/*
* Function irda_getvalue_confirm (obj_id, value, priv)
*
* Got answer from remote LM-IAS, just pass object to requester...
*
* Note : duplicate from above, but we need our own version that
* doesn't touch the dtsap_sel and save the full value structure...
*/
static void irda_getvalue_confirm(int result, __u16 obj_id,
struct ias_value *value, void *priv)
{
struct irda_sock *self;
self = priv;
if (!self) {
net_warn_ratelimited("%s: lost myself!\n", __func__);
return;
}
pr_debug("%s(%p)\n", __func__, self);
/* We probably don't need to make any more queries */
iriap_close(self->iriap);
self->iriap = NULL;
/* Check if request succeeded */
if (result != IAS_SUCCESS) {
pr_debug("%s(), IAS query failed! (%d)\n", __func__,
result);
self->errno = result; /* We really need it later */
/* Wake up any processes waiting for result */
wake_up_interruptible(&self->query_wait);
return;
}
/* Pass the object to the caller (so the caller must delete it) */
self->ias_result = value;
self->errno = 0;
/* Wake up any processes waiting for result */
wake_up_interruptible(&self->query_wait);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 108 | 86.40% | 7 | 53.85% |
Linus Torvalds | 5 | 4.00% | 1 | 7.69% |
Jean Tourrilhes | 4 | 3.20% | 1 | 7.69% |
Harvey Harrison | 3 | 2.40% | 1 | 7.69% |
Joe Perches | 3 | 2.40% | 2 | 15.38% |
Martin Dalecki | 2 | 1.60% | 1 | 7.69% |
Total | 125 | 100.00% | 13 | 100.00% |
/*
* Function irda_selective_discovery_indication (discovery)
*
* Got a selective discovery indication from IrLMP.
*
* IrLMP is telling us that this node is new and matching our hint bit
* filter. Wake up any process waiting for answer...
*/
static void irda_selective_discovery_indication(discinfo_t *discovery,
DISCOVERY_MODE mode,
void *priv)
{
struct irda_sock *self;
self = priv;
if (!self) {
net_warn_ratelimited("%s: lost myself!\n", __func__);
return;
}
/* Pass parameter to the caller */
self->cachedaddr = discovery->daddr;
/* Wake up process if its waiting for device to be discovered */
wake_up_interruptible(&self->query_wait);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 48 | 81.36% | 3 | 37.50% |
Jean Tourrilhes | 7 | 11.86% | 2 | 25.00% |
Martin Dalecki | 2 | 3.39% | 1 | 12.50% |
Harvey Harrison | 1 | 1.69% | 1 | 12.50% |
Joe Perches | 1 | 1.69% | 1 | 12.50% |
Total | 59 | 100.00% | 8 | 100.00% |
/*
* Function irda_discovery_timeout (priv)
*
* Timeout in the selective discovery process
*
* We were waiting for a node to be discovered, but nothing has come up
* so far. Wake up the user and tell him that we failed...
*/
static void irda_discovery_timeout(u_long priv)
{
struct irda_sock *self;
self = (struct irda_sock *) priv;
BUG_ON(self == NULL);
/* Nothing for the caller */
self->cachelog = NULL;
self->cachedaddr = 0;
self->errno = -ETIME;
/* Wake up process if its still waiting... */
wake_up_interruptible(&self->query_wait);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 52 | 88.14% | 2 | 50.00% |
Samuel Ortiz | 5 | 8.47% | 1 | 25.00% |
Jean Tourrilhes | 2 | 3.39% | 1 | 25.00% |
Total | 59 | 100.00% | 4 | 100.00% |
/*
* Function irda_open_tsap (self)
*
* Open local Transport Service Access Point (TSAP)
*
*/
static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name)
{
notify_t notify;
if (self->tsap) {
pr_debug("%s: busy!\n", __func__);
return -EBUSY;
}
/* Initialize callbacks to be used by the IrDA stack */
irda_notify_init(¬ify);
notify.connect_confirm = irda_connect_confirm;
notify.connect_indication = irda_connect_indication;
notify.disconnect_indication = irda_disconnect_indication;
notify.data_indication = irda_data_indication;
notify.udata_indication = irda_data_indication;
notify.flow_indication = irda_flow_indication;
notify.instance = self;
strncpy(notify.name, name, NOTIFY_MAX_NAME);
self->tsap = irttp_open_tsap(tsap_sel, DEFAULT_INITIAL_CREDIT,
¬ify);
if (self->tsap == NULL) {
pr_debug("%s(), Unable to allocate TSAP!\n",
__func__);
return -ENOMEM;
}
/* Remember which TSAP selector we actually got */
self->stsap_sel = self->tsap->stsap_sel;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 141 | 94.63% | 3 | 42.86% |
Joe Perches | 2 | 1.34% | 1 | 14.29% |
Martin Dalecki | 2 | 1.34% | 1 | 14.29% |
Harvey Harrison | 2 | 1.34% | 1 | 14.29% |
Jean Tourrilhes | 2 | 1.34% | 1 | 14.29% |
Total | 149 | 100.00% | 7 | 100.00% |
/*
* Function irda_open_lsap (self)
*
* Open local Link Service Access Point (LSAP). Used for opening Ultra
* sockets
*/
#ifdef CONFIG_IRDA_ULTRA
static int irda_open_lsap(struct irda_sock *self, int pid)
{
notify_t notify;
if (self->lsap) {
net_warn_ratelimited("%s(), busy!\n", __func__);
return -EBUSY;
}
/* Initialize callbacks to be used by the IrDA stack */
irda_notify_init(¬ify);
notify.udata_indication = irda_data_indication;
notify.instance = self;
strncpy(notify.name, "Ultra", NOTIFY_MAX_NAME);
self->lsap = irlmp_open_lsap(LSAP_CONNLESS, ¬ify, pid);
if (self->lsap == NULL) {
pr_debug("%s(), Unable to allocate LSAP!\n", __func__);
return -ENOMEM;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 96 | 92.31% | 3 | 42.86% |
Jeff Garzik | 4 | 3.85% | 1 | 14.29% |
Joe Perches | 2 | 1.92% | 2 | 28.57% |
Harvey Harrison | 2 | 1.92% | 1 | 14.29% |
Total | 104 | 100.00% | 7 | 100.00% |
#endif /* CONFIG_IRDA_ULTRA */
/*
* Function irda_find_lsap_sel (self, name)
*
* Try to lookup LSAP selector in remote LM-IAS
*
* Basically, we start a IAP query, and then go to sleep. When the query
* return, irda_getvalue_confirm will wake us up, and we can examine the
* result of the query...
* Note that in some case, the query fail even before we go to sleep,
* creating some races...
*/
static int irda_find_lsap_sel(struct irda_sock *self, char *name)
{
pr_debug("%s(%p, %s)\n", __func__, self, name);
if (self->iriap) {
net_warn_ratelimited("%s(): busy with a previous query\n",
__func__);
return -EBUSY;
}
self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
irda_getvalue_confirm);
if(self->iriap == NULL)
return -ENOMEM;
/* Treat unexpected wakeup as disconnect */
self->errno = -EHOSTUNREACH;
/* Query remote LM-IAS */
iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr,
name, "IrDA:TinyTP:LsapSel");
/* Wait for answer, if not yet finished (or failed) */
if (wait_event_interruptible(self->query_wait, (self->iriap==NULL)))
/* Treat signals as disconnect */
return -EHOSTUNREACH;
/* Check what happened */
if (self->errno)
{
/* Requested object/attribute doesn't exist */
if((self->errno == IAS_CLASS_UNKNOWN) ||
(self->errno == IAS_ATTRIB_UNKNOWN))
return -EADDRNOTAVAIL;
else
return -EHOSTUNREACH;
}
/* Get the remote TSAP selector */
switch (self->ias_result->type) {
case IAS_INTEGER:
pr_debug("%s() int=%d\n",
__func__, self->ias_result->t.integer);
if (self->ias_result->t.integer != -1)
self->dtsap_sel = self->ias_result->t.integer;
else
self->dtsap_sel = 0;
break;
default:
self->dtsap_sel = 0;
pr_debug("%s(), bad type!\n", __func__);
break;
}
if (self->ias_result)
irias_delete_value(self->ias_result);
if (self->dtsap_sel)
return 0;
return -EADDRNOTAVAIL;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 216 | 82.13% | 5 | 41.67% |
Jean Tourrilhes | 17 | 6.46% | 1 | 8.33% |
Linus Torvalds | 14 | 5.32% | 1 | 8.33% |
Jeff Garzik | 7 | 2.66% | 1 | 8.33% |
Harvey Harrison | 4 | 1.52% | 1 | 8.33% |
Joe Perches | 4 | 1.52% | 2 | 16.67% |
Martin Dalecki | 1 | 0.38% | 1 | 8.33% |
Total | 263 | 100.00% | 12 | 100.00% |
/*
* Function irda_discover_daddr_and_lsap_sel (self, name)
*
* This try to find a device with the requested service.
*
* It basically look into the discovery log. For each address in the list,
* it queries the LM-IAS of the device to find if this device offer
* the requested service.
* If there is more than one node supporting the service, we complain
* to the user (it should move devices around).
* The, we set both the destination address and the lsap selector to point
* on the service on the unique device we have found.
*
* Note : this function fails if there is more than one device in range,
* because IrLMP doesn't disconnect the LAP when the last LSAP is closed.
* Moreover, we would need to wait the LAP disconnection...
*/
static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name)
{
discinfo_t *discoveries; /* Copy of the discovery log */
int number; /* Number of nodes in the log */
int i;
int err = -ENETUNREACH;
__u32 daddr = DEV_ADDR_ANY; /* Address we found the service on */
__u8 dtsap_sel = 0x0; /* TSAP associated with it */
pr_debug("%s(), name=%s\n", __func__, name);
/* Ask lmp for the current discovery log
* Note : we have to use irlmp_get_discoveries(), as opposed
* to play with the cachelog directly, because while we are
* making our ias query, le log might change... */
discoveries = irlmp_get_discoveries(&number, self->mask.word,
self->nslots);
/* Check if the we got some results */
if (discoveries == NULL)
return -ENETUNREACH; /* No nodes discovered */
/*
* Now, check all discovered devices (if any), and connect
* client only about the services that the client is
* interested in...
*/
for(i = 0; i < number; i++) {
/* Try the address in the log */
self->daddr = discoveries[i].daddr;
self->saddr = 0x0;
pr_debug("%s(), trying daddr = %08x\n",
__func__, self->daddr);
/* Query remote LM-IAS for this service */
err = irda_find_lsap_sel(self, name);
switch (err) {
case 0:
/* We found the requested service */
if(daddr != DEV_ADDR_ANY) {
pr_debug("%s(), discovered service ''%s'' in two different devices !!!\n",
__func__, name);
self->daddr = DEV_ADDR_ANY;
kfree(discoveries);
return -ENOTUNIQ;
}
/* First time we found that one, save it ! */
daddr = self->daddr;
dtsap_sel = self->dtsap_sel;
break;
case -EADDRNOTAVAIL:
/* Requested service simply doesn't exist on this node */
break;
default:
/* Something bad did happen :-( */
pr_debug("%s(), unexpected IAS query failure\n",
__func__);
self->daddr = DEV_ADDR_ANY;
kfree(discoveries);
return -EHOSTUNREACH;
}
}
/* Cleanup our copy of the discovery log */
kfree(discoveries);
/* Check out what we found */
if(daddr == DEV_ADDR_ANY) {
pr_debug("%s(), cannot discover service ''%s'' in any device !!!\n",
__func__, name);
self->daddr = DEV_ADDR_ANY;
return -EADDRNOTAVAIL;
}
/* Revert back to discovered device & service */
self->daddr = daddr;
self->saddr = 0x0;
self->dtsap_sel = dtsap_sel;
pr_debug("%s(), discovered requested service ''%s'' at address %08x\n",
__func__, name, self->daddr);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 263 | 89.15% | 3 | 33.33% |
Jeff Garzik | 12 | 4.07% | 1 | 11.11% |
Harvey Harrison | 6 | 2.03% | 1 | 11.11% |
Joe Perches | 6 | 2.03% | 1 | 11.11% |
Linus Torvalds | 4 | 1.36% | 1 | 11.11% |
Jean Tourrilhes | 3 | 1.02% | 1 | 11.11% |
Martin Dalecki | 1 | 0.34% | 1 | 11.11% |
Total | 295 | 100.00% | 9 | 100.00% |
/*
* Function irda_getname (sock, uaddr, uaddr_len, peer)
*
* Return the our own, or peers socket address (sockaddr_irda)
*
*/
static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
struct sockaddr_irda saddr;
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
memset(&saddr, 0, sizeof(saddr));
if (peer) {
if (sk->sk_state != TCP_ESTABLISHED)
return -ENOTCONN;
saddr.sir_family = AF_IRDA;
saddr.sir_lsap_sel = self->dtsap_sel;
saddr.sir_addr = self->daddr;
} else {
saddr.sir_family = AF_IRDA;
saddr.sir_lsap_sel = self->stsap_sel;
saddr.sir_addr = self->saddr;
}
pr_debug("%s(), tsap_sel = %#x\n", __func__, saddr.sir_lsap_sel);
pr_debug("%s(), addr = %08x\n", __func__, saddr.sir_addr);
/* uaddr_len come to us uninitialised */
*uaddr_len = sizeof (struct sockaddr_irda);
memcpy(uaddr, &saddr, *uaddr_len);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 139 | 81.76% | 3 | 27.27% |
Eric Dumazet | 13 | 7.65% | 1 | 9.09% |
Samuel Ortiz | 5 | 2.94% | 1 | 9.09% |
Jeff Garzik | 4 | 2.35% | 1 | 9.09% |
David S. Miller | 3 | 1.76% | 1 | 9.09% |
Joe Perches | 2 | 1.18% | 1 | 9.09% |
Harvey Harrison | 2 | 1.18% | 1 | 9.09% |
Arnd Bergmann | 1 | 0.59% | 1 | 9.09% |
Arnaldo Carvalho de Melo | 1 | 0.59% | 1 | 9.09% |
Total | 170 | 100.00% | 11 | 100.00% |
/*
* Function irda_listen (sock, backlog)
*
* Just move to the listen state
*
*/
static int irda_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
int err = -EOPNOTSUPP;
lock_sock(sk);
if (