* 2 of the License, or (at your option) any later version.
* ============================================================================
* Due Credit:
* 2 of the License, or (at your option) any later version.
* ============================================================================
* Due Credit:
-* Wanpipe socket layer is based on Packet and
-* the X25 socket layers. The above sockets were
-* used for the specific use of Sangoma Technoloiges
-* API programs.
-* Packet socket Authors: Ross Biro, Fred N. van Kempen and
+* Wanpipe socket layer is based on Packet and
+* the X25 socket layers. The above sockets were
+* used for the specific use of Sangoma Technologies
+* API programs.
+* Packet socket Authors: Ross Biro, Fred N. van Kempen and
* Alan Cox.
* X25 socket Author: Jonathan Naylor.
* ============================================================================
* Alan Cox.
* X25 socket Author: Jonathan Naylor.
* ============================================================================
* Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets.
* Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call.
* Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem.
* Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets.
* Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call.
* Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem.
* simultaneously without conflicts.
* Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as
* CHDLC, Frame Relay and HDLC API.
* Jan 17, 2000 Nenad Corbic o Initial version, based on AF_PACKET socket.
* simultaneously without conflicts.
* Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as
* CHDLC, Frame Relay and HDLC API.
* Jan 17, 2000 Nenad Corbic o Initial version, based on AF_PACKET socket.
#define DBG_PRINTK(format, a...) printk(format, ## a)
#else
#define DBG_PRINTK(format, a...)
#define DBG_PRINTK(format, a...) printk(format, ## a)
#else
#define DBG_PRINTK(format, a...)
* Each packet is enqueud into sk->sk_write_queue transmit
* queue. When the packet is enqueued, a delayed transmit
* Each packet is enqueud into sk->sk_write_queue transmit
* queue. When the packet is enqueued, a delayed transmit
- * from the sk->sk_write_queue transmit queue and sends it
- * to the deriver via dev->hard_start_xmit(skb, dev) function.
+ * from the sk->sk_write_queue transmit queue and sends it
+ * to the deriver via dev->hard_start_xmit(skb, dev) function.
* Note, this function is actual a function pointer of if_send()
* routine in the wanpipe driver.
*
* X25API GUARANTEED DELIVERY:
*
* Note, this function is actual a function pointer of if_send()
* routine in the wanpipe driver.
*
* X25API GUARANTEED DELIVERY:
*
- * In order to provide 100% guaranteed packet delivery,
- * an atomic 'packet_sent' counter is implemented. Counter
- * is incremented for each packet enqueued
+ * In order to provide 100% guaranteed packet delivery,
+ * an atomic 'packet_sent' counter is implemented. Counter
+ * is incremented for each packet enqueued
* passes the packet to the driver. Before each send(), a poll
* routine checks the sock resources The maximum value of
* packet sent counter is 1, thus if one packet is queued, the
* passes the packet to the driver. Before each send(), a poll
* routine checks the sock resources The maximum value of
* packet sent counter is 1, thus if one packet is queued, the
* function, wanpipe_rcv() to queue the incoming packets
* into an AF_WANPIPE socket queue. Based on wanpipe_rcv()
* return code, the driver knows whether the packet was
* function, wanpipe_rcv() to queue the incoming packets
* into an AF_WANPIPE socket queue. Based on wanpipe_rcv()
* return code, the driver knows whether the packet was
- * successfully queued. If the socket queue is full,
- * protocol flow control is used by the driver, if any,
+ * successfully queued. If the socket queue is full,
+ * protocol flow control is used by the driver, if any,
* bit which signals the socket to kick the wanpipe driver
* bottom half hander when the socket queue is partialy
* empty. wanpipe_recvmsg() function performs this action.
* bit which signals the socket to kick the wanpipe driver
* bottom half hander when the socket queue is partialy
* empty. wanpipe_recvmsg() function performs this action.
- * flow control is available.
- *
- * In case of streaming protocols like CHDLC, packets will
- * be dropped but the statistics will be generated.
+ * flow control is available.
+ *
+ * In case of streaming protocols like CHDLC, packets will
+ * be dropped but the statistics will be generated.
struct net_device *dev; /* Bounded device */
unsigned short lcn; /* Binded LCN */
unsigned char svc; /* 0=pvc, 1=svc */
struct net_device *dev; /* Bounded device */
unsigned short lcn; /* Binded LCN */
unsigned char svc; /* 0=pvc, 1=svc */
*
* Wanpipe socket bottom half handler. This function
* is called by the WANPIPE device drivers to queue a
*
* Wanpipe socket bottom half handler. This function
* is called by the WANPIPE device drivers to queue a
- * incoming packet into the socket receive queue.
- * Once the packet is queued, all processes waiting to
+ * incoming packet into the socket receive queue.
+ * Once the packet is queued, all processes waiting to
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
if (dev->hard_header_parse)
sll->sll_halen = dev->hard_header_parse(skb, sll->sll_addr);
- * WAN_PACKET_ASYC : Asynchronous data like place call, which should
- * be passed up the listening sock.
- * WAN_PACKET_ERR : Asynchronous data like clear call or restart
- * which should go into an error queue.
- */
+ * WAN_PACKET_ASYC : Asynchronous data like place call, which should
+ * be passed up the listening sock.
+ * WAN_PACKET_ERR : Asynchronous data like clear call or restart
+ * which should go into an error queue.
+ */
- /* Bug fix: update Mar6.
- * Do not set the sock lcn number here, since
- * cmd is not guaranteed to be executed on the
- * board, thus Lcn could be wrong */
+ /* Bug fix: update Mar6.
+ * Do not set the sock lcn number here, since
+ * cmd is not guaranteed to be executed on the
+ * board, thus Lcn could be wrong */
*
* Wanpipe LISTEN socket bottom half handler. This function
* is called by the WANPIPE device drivers to queue an
*
* Wanpipe LISTEN socket bottom half handler. This function
* is called by the WANPIPE device drivers to queue an
- * incoming call into the socket listening queue.
- * Once the packet is queued, the waiting accept() process
+ * incoming call into the socket listening queue.
+ * Once the packet is queued, the waiting accept() process
- * When we do a bind to a device structre, we
- * bind a newly created socket into "chan->sk". Thus,
- * when accept receives the skb packet, it will know
+ * When we do a bind to a device structre, we
+ * bind a newly created socket into "chan->sk". Thus,
+ * when accept receives the skb packet, it will know
* from which dev it came form, and in turn it will know
* the address of the new sock.
*
* from which dev it came form, and in turn it will know
* the address of the new sock.
*
wanpipe_opt *wp = wp_sk(sk), *newwp;
struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb;
struct sock *newsk;
wanpipe_opt *wp = wp_sk(sk), *newwp;
struct wan_sockaddr_ll *sll = (struct wan_sockaddr_ll*)skb->cb;
struct sock *newsk;
card = (sdla_t*)wp->card;
if (!card){
printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n");
return -ENODEV;
}
card = (sdla_t*)wp->card;
if (!card){
printk(KERN_INFO "wansock: LISTEN ERROR, No Card\n");
return -ENODEV;
}
dev = wanpipe_find_free_dev(card);
if (!dev){
printk(KERN_INFO "wansock: LISTEN ERROR, No Free Device\n");
return -ENODEV;
}
dev = wanpipe_find_free_dev(card);
if (!dev){
printk(KERN_INFO "wansock: LISTEN ERROR, No Free Device\n");
return -ENODEV;
}
chan->state = WANSOCK_CONNECTING;
/* Allocate a new sock, which accept will bind
chan->state = WANSOCK_CONNECTING;
/* Allocate a new sock, which accept will bind
- * bind the mail box to the sock. It will be
- * used by the ioctl call to read call information
- * and to execute commands.
- */
- if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {
+ * bind the mail box to the sock. It will be
+ * used by the ioctl call to read call information
+ * and to execute commands.
+ */
+ if ((mbox_ptr = kzalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) {
memcpy(mbox_ptr,skb->data,skb->len);
/* Register the lcn on which incoming call came
memcpy(mbox_ptr,skb->data,skb->len);
/* Register the lcn on which incoming call came
/* We must do this manually, since the sock_queue_rcv_skb()
* function sets the skb->dev to NULL. However, we use
/* We must do this manually, since the sock_queue_rcv_skb()
* function sets the skb->dev to NULL. However, we use
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
skb_set_owner_r(skb, sk);
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
* FIXME: wanpipe_opt has to include a sock in its definition and stop using
* sk_protinfo, but this code is not even compilable now, so lets leave it for
* later.
* FIXME: wanpipe_opt has to include a sock in its definition and stop using
* sk_protinfo, but this code is not even compilable now, so lets leave it for
* later.
if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, &wanpipe_proto, 1)) == NULL)
return NULL;
if ((sk = sk_alloc(PF_WANPIPE, GFP_ATOMIC, &wanpipe_proto, 1)) == NULL)
return NULL;
init_timer(&wan_opt->tx_timer);
wan_opt->tx_timer.data = (unsigned long)sk;
wan_opt->tx_timer.function = wanpipe_delayed_transmit;
init_timer(&wan_opt->tx_timer);
wan_opt->tx_timer.data = (unsigned long)sk;
wan_opt->tx_timer.function = wanpipe_delayed_transmit;
* During socket bind() sk->sk_bound_dev_if is initialized
* to a correct network device. This number is used
* to find a network device to which the packet should
* be passed to.
*
* During socket bind() sk->sk_bound_dev_if is initialized
* to a correct network device. This number is used
* to find a network device to which the packet should
* be passed to.
*
- * Each packet is queued into sk->sk_write_queue and
- * delayed transmit bottom half handler is marked for
+ * Each packet is queued into sk->sk_write_queue and
+ * delayed transmit bottom half handler is marked for
if (!sock_flag(sk, SOCK_ZAPPED))
return -ENETDOWN;
if (sk->sk_state != WANSOCK_CONNECTED)
if (!sock_flag(sk, SOCK_ZAPPED))
return -ENETDOWN;
if (sk->sk_state != WANSOCK_CONNECTED)
if (sock->type == SOCK_RAW)
reserve = dev->hard_header_len;
if (len > dev->mtu+reserve){
if (sock->type == SOCK_RAW)
reserve = dev->hard_header_len;
if (len > dev->mtu+reserve){
if (!(test_and_set_bit(0, &wp->timer)))
mod_timer(&wp->tx_timer, jiffies + 1);
if (!(test_and_set_bit(0, &wp->timer)))
mod_timer(&wp->tx_timer, jiffies + 1);
- * from sk->sk_write_queue and passes them to the
- * driver. If the driver is busy, the packet is
- * re-enqueued.
+ * from sk->sk_write_queue and passes them to the
+ * driver. If the driver is busy, the packet is
+ * re-enqueued.
if (sk->sk_state != WANSOCK_CONNECTED || !sock_flag(sk, SOCK_ZAPPED)) {
clear_bit(0, &wp->timer);
DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n");
return;
}
if (sk->sk_state != WANSOCK_CONNECTED || !sock_flag(sk, SOCK_ZAPPED)) {
clear_bit(0, &wp->timer);
DBG_PRINTK(KERN_INFO "wansock: Tx Timer, State not CONNECTED\n");
return;
}
if (atomic_read(&card->u.x.command_busy)){
wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
add_timer(&wp->tx_timer);
if (atomic_read(&card->u.x.command_busy)){
wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
add_timer(&wp->tx_timer);
if (test_and_set_bit(0,&wanpipe_tx_critical)){
printk(KERN_INFO "WanSock: Tx timer critical %s\n",dev->name);
wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
add_timer(&wp->tx_timer);
return;
if (test_and_set_bit(0,&wanpipe_tx_critical)){
printk(KERN_INFO "WanSock: Tx timer critical %s\n",dev->name);
wp->tx_timer.expires = jiffies + SLOW_BACKOFF;
add_timer(&wp->tx_timer);
return;
skb_queue_head(&sk->sk_write_queue,skb);
clear_bit(0,&wanpipe_tx_critical);
return;
}else{
/* Packet Sent successful. Check for more packets
skb_queue_head(&sk->sk_write_queue,skb);
clear_bit(0,&wanpipe_tx_critical);
return;
}else{
/* Packet Sent successful. Check for more packets
*
* Execute x25api commands. The atomic variable
* chan->command is used to indicate to the driver that
* command is pending for execution. The acutal command
*
* Execute x25api commands. The atomic variable
* chan->command is used to indicate to the driver that
* command is pending for execution. The acutal command
* (wp_sk(sk)->mbox).
*
* The sock private structure, mbox is
* used as shared memory between sock and the driver.
* Driver uses the sock mbox to execute the command
* (wp_sk(sk)->mbox).
*
* The sock private structure, mbox is
* used as shared memory between sock and the driver.
* Driver uses the sock mbox to execute the command
*
* For all command except PLACE CALL, the function
* waits for the result. PLACE CALL can be ether
*
* For all command except PLACE CALL, the function
* waits for the result. PLACE CALL can be ether
wanpipe_common_t *chan=NULL;
int err=0;
DECLARE_WAITQUEUE(wait, current);
wanpipe_common_t *chan=NULL;
int err=0;
DECLARE_WAITQUEUE(wait, current);
dev = dev_get_by_index(sk->sk_bound_dev_if);
if (dev == NULL){
printk(KERN_INFO "wansock: Exec failed no dev %i\n",
dev = dev_get_by_index(sk->sk_bound_dev_if);
if (dev == NULL){
printk(KERN_INFO "wansock: Exec failed no dev %i\n",
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sk_sleep,&wait);
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sk_sleep,&wait);
if (atomic_read(&sk->sk_refcnt) != 1) {
atomic_set(&sk->sk_refcnt, 1);
DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n",
if (atomic_read(&sk->sk_refcnt) != 1) {
atomic_set(&sk->sk_refcnt, 1);
DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n",
*===========================================================*/
static void wanpipe_unlink_driver (struct sock *sk)
{
*===========================================================*/
static void wanpipe_unlink_driver (struct sock *sk)
{
- * Close a PACKET socket. This is fairly simple. We
- * immediately go to 'closed' state and remove our
+ * Close a PACKET socket. This is fairly simple. We
+ * immediately go to 'closed' state and remove our
- * will run after we kill the sock. Timer code will
- * try to access the sock which has been killed and cause
- * kernel panic */
+ * will run after we kill the sock. Timer code will
+ * try to access the sock which has been killed and cause
+ * kernel panic */
- * During sock shutdown, if the sock state is
- * WANSOCK_CONNECTED and there is transmit data
- * pending. Wait until data is released
+ * During sock shutdown, if the sock state is
+ * WANSOCK_CONNECTED and there is transmit data
+ * pending. Wait until data is released
* release any resources and links that bind the sock
* to the driver. It also changes the state of the
* sock to WANSOCK_DISCONNECTED
* release any resources and links that bind the sock
* to the driver. It also changes the state of the
* sock to WANSOCK_DISCONNECTED
* envoke the kill routines for pending socks.
*===========================================================*/
* envoke the kill routines for pending socks.
*===========================================================*/
*
* This is a function which performs actual killing
* of the sock. It releases socket resources,
*
* This is a function which performs actual killing
* of the sock. It releases socket resources,
*===========================================================*/
static void wanpipe_kill_sock_timer (unsigned long data)
*===========================================================*/
static void wanpipe_kill_sock_timer (unsigned long data)
if (test_bit(1,&wanpipe_tx_critical)){
sk->sk_timer.expires = jiffies + 10;
add_timer(&sk->sk_timer);
return;
}
if (test_bit(1,&wanpipe_tx_critical)){
sk->sk_timer.expires = jiffies + 10;
add_timer(&sk->sk_timer);
return;
}
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&sk->sk_error_queue);
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&sk->sk_error_queue);
if (atomic_read(&sk->sk_rmem_alloc) ||
atomic_read(&sk->sk_wmem_alloc)) {
del_timer(&sk->sk_timer);
if (atomic_read(&sk->sk_rmem_alloc) ||
atomic_read(&sk->sk_wmem_alloc)) {
del_timer(&sk->sk_timer);
strlcpy(name,sll->sll_device,sizeof(name));
dev = dev_get_by_name(name);
if (dev == NULL){
strlcpy(name,sll->sll_device,sizeof(name));
dev = dev_get_by_name(name);
if (dev == NULL){
* the interface is taken. This avoids race conditions.
*===========================================================*/
* the interface is taken. This avoids race conditions.
*===========================================================*/
* Check that device name belongs to a particular card.
*===========================================================*/
* Check that device name belongs to a particular card.
*===========================================================*/
if (test_and_set_bit(0,&find_free_critical)){
printk(KERN_INFO "CRITICAL in Find Free\n");
if (test_and_set_bit(0,&find_free_critical)){
printk(KERN_INFO "CRITICAL in Find Free\n");
* Crates AF_WANPIPE socket.
*===========================================================*/
static int wanpipe_create(struct socket *sock, int protocol)
{
struct sock *sk;
* Crates AF_WANPIPE socket.
*===========================================================*/
static int wanpipe_create(struct socket *sock, int protocol)
{
struct sock *sk;
//FIXME: This checks for root user, SECURITY ?
//if (!capable(CAP_NET_RAW))
// return -EPERM;
//FIXME: This checks for root user, SECURITY ?
//if (!capable(CAP_NET_RAW))
// return -EPERM;
/* We must disable interrupts because the ISR
* can also change the list */
set_bit(1,&wanpipe_tx_critical);
/* We must disable interrupts because the ISR
* can also change the list */
set_bit(1,&wanpipe_tx_critical);
skb = skb_dequeue(&sk->sk_error_queue);
}else{
skb=skb_recv_datagram(sk,flags,1,&err);
}
/*
skb = skb_dequeue(&sk->sk_error_queue);
}else{
skb=skb_recv_datagram(sk,flags,1,&err);
}
/*
* If socket receive buffer is full and driver cannot
* pass data up the sock, it sets a packet_block flag.
* If socket receive buffer is full and driver cannot
* pass data up the sock, it sets a packet_block flag.
- * This function check that flag and if sock receive
- * queue has room it kicks the driver BH handler.
+ * This function check that flag and if sock receive
+ * queue has room it kicks the driver BH handler.
if (atomic_read(&sk->sk_rmem_alloc) <
((unsigned)sk->sk_rcvbuf * 0.9)) {
printk(KERN_INFO "wansock: Queuing task for wanpipe\n");
if (atomic_read(&sk->sk_rmem_alloc) <
((unsigned)sk->sk_rcvbuf * 0.9)) {
printk(KERN_INFO "wansock: Queuing task for wanpipe\n");
* User can use this function to get sock address
* information. Not very useful for Sangoma's purposes.
*===========================================================*/
* User can use this function to get sock address
* information. Not very useful for Sangoma's purposes.
*===========================================================*/
if (msg == NETDEV_UNREGISTER) {
printk(KERN_INFO "wansock: Unregistering Device: %s\n",
if (msg == NETDEV_UNREGISTER) {
printk(KERN_INFO "wansock: Unregistering Device: %s\n",
* Execute a user commands, and set socket options.
*
* FIXME: More thought should go into this function.
* Execute a user commands, and set socket options.
*
* FIXME: More thought should go into this function.
if ((err=put_user(chan->state, &dbg_data->debug[cnt].d_state)))
return err;
if ((err=put_user(chan->svc, &dbg_data->debug[cnt].svc)))
return err;
if ((err=put_user(chan->state, &dbg_data->debug[cnt].d_state)))
return err;
if ((err=put_user(chan->svc, &dbg_data->debug[cnt].svc)))
return err;
&dbg_data->debug[cnt].rblock)))
return err;
if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name)))
return -EFAULT;
}
&dbg_data->debug[cnt].rblock)))
return err;
if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name)))
return -EFAULT;
}
* Pass up the contents of socket MBOX to the user.
*===========================================================*/
* Pass up the contents of socket MBOX to the user.
*===========================================================*/
if ((err=put_user(mbox_ptr->cmd.result, &usr_data->hdr.result)))
return err;
if ((err=put_user(mbox_ptr->cmd.lcn, &usr_data->hdr.lcn)))
if ((err=put_user(mbox_ptr->cmd.result, &usr_data->hdr.result)))
return err;
if ((err=put_user(mbox_ptr->cmd.lcn, &usr_data->hdr.lcn)))
*===========================================================*/
static int set_ioctl_cmd (struct sock *sk, void *arg)
*===========================================================*/
static int set_ioctl_cmd (struct sock *sk, void *arg)
wp_sk(sk)->mbox = mbox_ptr;
wanpipe_link_driver(dev,sk);
wp_sk(sk)->mbox = mbox_ptr;
wanpipe_link_driver(dev,sk);
- * This option is only for X25API protocol, for other
- * protocol like chdlc enable streaming mode,
- * where multiple packets can be pending in the socket
- * transmit queue */
+ * This option is only for X25API protocol, for other
+ * protocol like chdlc enable streaming mode,
+ * where multiple packets can be pending in the socket
+ * transmit queue */
- /* This is x25 specific area if protocol doesn't
- * match, return error */
+ /* This is x25 specific area if protocol doesn't
+ * match, return error */
card->sk=sk;
card->func=wanpipe_listen_rcv;
sock_set_flag(sk, SOCK_ZAPPED);
card->sk=sk;
card->func=wanpipe_listen_rcv;
sock_set_flag(sk, SOCK_ZAPPED);
- /* Update. Mar6 2000.
- * Do not set the sock lcn number here, since
- * it is done in wanpipe_listen_rcv().
- */
- if (sk->sk_state == WANSOCK_CONNECTED) {
- wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;
+ /* Update. Mar6 2000.
+ * Do not set the sock lcn number here, since
+ * it is done in wanpipe_listen_rcv().
+ */
+ if (sk->sk_state == WANSOCK_CONNECTED) {
+ wp->lcn = ((mbox_cmd_t*)wp->mbox)->cmd.lcn;
- * if so, check whether user wants to wait until data
- * is transmitted, or clear a call and drop packets */
-
+ * if so, check whether user wants to wait until data
+ * is transmitted, or clear a call and drop packets */
+
- * if so, check whether user wants to wait until data
- * is transmitted, or reset a call and drop packets */
-
+ * if so, check whether user wants to wait until data
+ * is transmitted, or reset a call and drop packets */
+
- * ACCEPT() System call. X25API Specific function.
- * For each incoming call, create a new socket and
- * return it to the user.
+ * ACCEPT() System call. X25API Specific function.
+ * For each incoming call, create a new socket and
+ * return it to the user.
*=====================================================================*/
static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags)
*=====================================================================*/
static int wanpipe_accept(struct socket *sock, struct socket *newsock, int flags)
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sk_sleep,&wait);
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sk_sleep,&wait);
*
* CONNECT() System Call. X25API specific function
* Check the state of the sock, and execute PLACE_CALL command.
*
* CONNECT() System Call. X25API specific function
* Check the state of the sock, and execute PLACE_CALL command.
.connect = wanpipe_connect,
.socketpair = sock_no_socketpair,
.accept = wanpipe_accept,
.connect = wanpipe_connect,
.socketpair = sock_no_socketpair,
.accept = wanpipe_accept,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
.shutdown = sock_no_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,