📄 af_wanpipe.c
字号:
if ((err=put_user(1, &dbg_data->debug[cnt].free))) return err; if ((err=put_user(sk->state, &dbg_data->debug[cnt].sk_state))) return err; if ((err=put_user(sk->rcvbuf, &dbg_data->debug[cnt].rcvbuf))) return err; if ((err=put_user(atomic_read(&sk->rmem_alloc), &dbg_data->debug[cnt].rmem))) return err; if ((err=put_user(atomic_read(&sk->wmem_alloc), &dbg_data->debug[cnt].wmem))) return err; if ((err=put_user(sk->sndbuf, &dbg_data->debug[cnt].sndbuf))) return err; if ((err=put_user(sk_count, &dbg_data->debug[cnt].sk_count))) return err; if ((err=put_user(sk->protinfo.af_wanpipe->poll_cnt, &dbg_data->debug[cnt].poll_cnt))) return err; if ((err=put_user(sk->bound_dev_if, &dbg_data->debug[cnt].bound))) return err; if (sk->bound_dev_if){ dev = dev_get_by_index(sk->bound_dev_if); if (!dev) continue; chan=dev->priv; dev_put(dev); 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(atomic_read(&chan->command), &dbg_data->debug[cnt].command))) return err; if (sk->protinfo.af_wanpipe){ sdla_t *card = (sdla_t*)sk->protinfo.af_wanpipe->card; if (card){ if ((err=put_user(atomic_read(&card->u.x.command_busy), &dbg_data->debug[cnt].cmd_busy))) return err; } if ((err=put_user(sk->protinfo.af_wanpipe->lcn, &dbg_data->debug[cnt].lcn))) return err; if (sk->protinfo.af_wanpipe->mbox){ if ((err=put_user(1, &dbg_data->debug[cnt].mbox))) return err; } } if ((err=put_user(atomic_read(&chan->receive_block), &dbg_data->debug[cnt].rblock))) return err; if (copy_to_user(dbg_data->debug[cnt].name, dev->name, strlen(dev->name))) return -EFAULT; } if (++cnt == MAX_NUM_DEBUG) break; } return 0;}/*============================================================ * get_ioctl_cmd * * Pass up the contents of socket MBOX to the user. *===========================================================*/static int get_ioctl_cmd (struct sock *sk, void *arg){ x25api_t *usr_data = (x25api_t *)arg; mbox_cmd_t *mbox_ptr; int err; if (usr_data == NULL) return -EINVAL; if (!sk->protinfo.af_wanpipe->mbox){ return -EINVAL; } mbox_ptr = (mbox_cmd_t *)sk->protinfo.af_wanpipe->mbox; if ((err=put_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm))) return err; if ((err=put_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause))) return err; if ((err=put_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn))) return err; if ((err=put_user(mbox_ptr->cmd.length, &usr_data->hdr.length))) return err; 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))) return err; if (mbox_ptr->cmd.length > 0){ if (mbox_ptr->cmd.length > X25_MAX_DATA) return -EINVAL; if (copy_to_user(usr_data->data, mbox_ptr->data, mbox_ptr->cmd.length)){ printk(KERN_INFO "wansock: Copy failed !!!\n"); return -EFAULT; } } return 0;} /*============================================================ * set_ioctl_cmd * * Before command can be execute, socket MBOX must * be created, and initialized with user data. *===========================================================*/static int set_ioctl_cmd (struct sock *sk, void *arg){ x25api_t *usr_data = (x25api_t *)arg; mbox_cmd_t *mbox_ptr; int err; if (!sk->protinfo.af_wanpipe->mbox){ void *mbox_ptr; netdevice_t *dev = dev_get_by_index(sk->bound_dev_if); if (!dev) return -ENODEV; dev_put(dev); if ((mbox_ptr = kmalloc(sizeof(mbox_cmd_t), GFP_ATOMIC)) == NULL) return -ENOMEM; memset(mbox_ptr, 0, sizeof(mbox_cmd_t)); sk->protinfo.af_wanpipe->mbox = mbox_ptr; wanpipe_link_driver(dev,sk); } mbox_ptr = (mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox; memset(mbox_ptr, 0, sizeof(mbox_cmd_t)); if (usr_data == NULL){ return 0; } if ((err=get_user(mbox_ptr->cmd.qdm, &usr_data->hdr.qdm))) return err; if ((err=get_user(mbox_ptr->cmd.cause, &usr_data->hdr.cause))) return err; if ((err=get_user(mbox_ptr->cmd.diagn, &usr_data->hdr.diagn))) return err; if ((err=get_user(mbox_ptr->cmd.length, &usr_data->hdr.length))) return err; if ((err=get_user(mbox_ptr->cmd.result, &usr_data->hdr.result))) return err; if (mbox_ptr->cmd.length > 0){ if (mbox_ptr->cmd.length > X25_MAX_DATA) return -EINVAL; if (copy_from_user(mbox_ptr->data, usr_data->data, mbox_ptr->cmd.length)){ printk(KERN_INFO "Copy failed\n"); return -EFAULT; } } return 0;}/*====================================================================== * wanpipe_poll * * Datagram poll: Again totally generic. This also handles * sequenced packet sockets providing the socket receive queue * is only ever holding data ready to receive. * * Note: when you _don't_ use this routine for this protocol, * and you use a different write policy from sock_writeable() * then please supply your own write_space callback. *=====================================================================*/unsigned int wanpipe_poll(struct file * file, struct socket *sock, poll_table *wait){ struct sock *sk = sock->sk; unsigned int mask; ++sk->protinfo.af_wanpipe->poll_cnt; poll_wait(file, sk->sleep, wait); mask = 0; /* exceptional events? */ if (sk->err || !skb_queue_empty(&sk->error_queue)){ mask |= POLLPRI; return mask; } if (sk->shutdown & RCV_SHUTDOWN) mask |= POLLHUP; /* readable? */ if (!skb_queue_empty(&sk->receive_queue)){ mask |= POLLIN | POLLRDNORM; } /* connection hasn't started yet */ if (sk->state == WANSOCK_CONNECTING){ return mask; } if (sk->state == WANSOCK_DISCONNECTED){ mask = POLLPRI; return mask; } /* This check blocks the user process if there is * a packet already queued in the socket write 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 */ if (sk->num == htons(X25_PROT)){ if (atomic_read(&sk->protinfo.af_wanpipe->packet_sent)) return mask; } /* writable? */ if (sock_writeable(sk)){ mask |= POLLOUT | POLLWRNORM | POLLWRBAND; }else{ #ifdef LINUX_2_4 set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); #else sk->socket->flags |= SO_NOSPACE; #endif } return mask;}/*====================================================================== * wanpipe_listen * * X25API Specific function. Set a socket into LISTENING MODE. *=====================================================================*/static int wanpipe_listen(struct socket *sock, int backlog){ struct sock *sk = sock->sk; /* This is x25 specific area if protocol doesn't * match, return error */ if (sk->num != htons(X25_PROT)) return -EINVAL; if (sk->state == WANSOCK_BIND_LISTEN) { sk->max_ack_backlog = backlog; sk->state = WANSOCK_LISTEN; return 0; }else{ printk(KERN_INFO "wansock: Listening sock was not binded\n"); } return -EINVAL;}/*====================================================================== * wanpipe_link_card * * Connects the listening socket to the driver *=====================================================================*/static int wanpipe_link_card (struct sock *sk){ sdla_t *card; card = (sdla_t*)sk->protinfo.af_wanpipe->card; if (!card) return -ENOMEM; if ((card->sk != NULL) || (card->func != NULL)){ printk(KERN_INFO "wansock: Listening queue is already established\n"); return -EINVAL; } card->sk=sk; card->func=wanpipe_listen_rcv; sk->zapped=1; return 0;}/*====================================================================== * wanpipe_listen * * X25API Specific function. Disconnect listening socket from * the driver. *=====================================================================*/static void wanpipe_unlink_card (struct sock *sk){ sdla_t *card; card = (sdla_t*)sk->protinfo.af_wanpipe->card; if (card){ card->sk=NULL; card->func=NULL; }}/*====================================================================== * wanpipe_exec_cmd * * Ioctl function calls this function to execute user command. * Connect() sytem call also calls this function to execute * place call. This function blocks until command is executed. *=====================================================================*/static int wanpipe_exec_cmd(struct sock *sk, int cmd, unsigned int flags){ int err = -EINVAL; mbox_cmd_t *mbox_ptr = (mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox; if (!mbox_ptr){ printk(KERN_INFO "NO MBOX PTR !!!!!\n"); return -EINVAL; } /* This is x25 specific area if protocol doesn't * match, return error */ if (sk->num != htons(X25_PROT)) return -EINVAL; switch (cmd){ case SIOC_WANPIPE_ACCEPT_CALL: if (sk->state != WANSOCK_CONNECTING){ err = -EHOSTDOWN; break; } err = execute_command(sk,X25_ACCEPT_CALL,0); if (err < 0) break; /* Update. Mar6 2000. * Do not set the sock lcn number here, since * it is done in wanpipe_listen_rcv(). */ if (sk->state == WANSOCK_CONNECTED){ sk->protinfo.af_wanpipe->lcn = ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: Accept OK %i\n", sk->protinfo.af_wanpipe->lcn ); err = 0; }else{ DBG_PRINTK (KERN_INFO "\nwansock: Accept Failed %i\n", sk->protinfo.af_wanpipe->lcn); sk->protinfo.af_wanpipe->lcn = 0; err = -ECONNREFUSED; } break; case SIOC_WANPIPE_CLEAR_CALL: if (sk->state == WANSOCK_DISCONNECTED){ err = -EINVAL; break; } /* Check if data buffers are pending for transmission, * if so, check wheter user wants to wait untill data * is transmitted, or clear a call and drop packets */ if (atomic_read(&sk->wmem_alloc) || check_driver_busy(sk)){ mbox_cmd_t *mbox = sk->protinfo.af_wanpipe->mbox; if (mbox->cmd.qdm & 0x80){ mbox->cmd.result = 0x35; err = -EAGAIN; break; } } sk->state = WANSOCK_DISCONNECTING; err = execute_command(sk,X25_CLEAR_CALL,0); if (err < 0) break; err = -ECONNREFUSED; if (sk->state == WANSOCK_DISCONNECTED){ DBG_PRINTK(KERN_INFO "\nwansock: CLEAR OK %i\n", sk->protinfo.af_wanpipe->lcn); sk->protinfo.af_wanpipe->lcn=0; err = 0; } break; case SIOC_WANPIPE_RESET_CALL: if (sk->state != WANSOCK_CONNECTED){ err = -EINVAL; break; } /* Check if data buffers are pending for transmission, * if so, check wheter user wants to wait untill data * is transmitted, or reset a call and drop packets */ if (atomic_read(&sk->wmem_alloc) || check_driver_busy(sk)){ mbox_cmd_t *mbox = sk->protinfo.af_wanpipe->mbox; if (mbox->cmd.qdm & 0x80){ mbox->cmd.result = 0x35; err = -EAGAIN; break; } } err = execute_command(sk, X25_RESET,0); if (err < 0) break; err = mbox_ptr->cmd.result; break; case X25_PLACE_CALL: err=execute_command(sk,X25_PLACE_CALL,flags); if (err < 0) break; if (sk->state == WANSOCK_CONNECTED){ sk->protinfo.af_wanpipe->lcn = ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: PLACE CALL OK %i\n", sk->protinfo.af_wanpipe->lcn); err = 0; }else if (sk->state == WANSOCK_CONNECTING && (flags & O_NONBLOCK)){ sk->protinfo.af_wanpipe->lcn = ((mbox_cmd_t*)sk->protinfo.af_wanpipe->mbox)->cmd.lcn; DBG_PRINTK(KERN_INFO "\nwansock: Place Call OK: Waiting %i\n", sk->protinfo.af_wanpipe->lcn); err = 0; }else{ DBG_PRINTK(KERN_INFO "\nwansock: Place call Failed\n"); err = -ECONNREFUSED; } break; default: return -EINVAL; } return err;}static int check_driver_busy (struct sock *sk){ netdevice_t *dev = dev_get_by_index(sk->bound_dev_if); wanpipe_common_t *chan; if (!dev) return 0; dev_put(dev); if ((chan=dev->priv) == NULL) return 0; return atomic_read(&chan->driver_busy);}/*====================================================================== * wanpipe_accept * * ACCEPT() System call.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -