/* * Queue up a socket with data pending. If there are idle nfsd * processes, wake 'em up. * */ static void svc_sock_enqueue(struct svc_sock *svsk) { struct svc_serv *serv = svsk->sk_server; struct svc_rqst *rqstp; if (!(svsk->sk_flags & ( (1<<SK_CONN)|(1<<SK_DATA)|(1<<SK_CLOSE)) )) return; if (test_bit(SK_DEAD, &svsk->sk_flags)) return; spin_lock_bh(&serv->sv_lock); if (!list_empty(&serv->sv_threads) && !list_empty(&serv->sv_sockets)) printk(KERN_ERR "svc_sock_enqueue: threads and sockets both waiting??\n"); if (test_bit(SK_BUSY, &svsk->sk_flags)) { /* Don't enqueue socket while daemon is receiving */ dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk); goto out_unlock; } if (((svsk->sk_reserved + serv->sv_bufsz)*2 > sock_wspace(svsk->sk_sk)) && !test_bit(SK_CLOSE, &svsk->sk_flags) && !test_bit(SK_CONN, &svsk->sk_flags)) { /* Don't enqueue while not enough space for reply */ dprintk("svc: socket %p no space, %d*2 > %ld, not enqueued\n", svsk->sk_sk, svsk->sk_reserved+serv->sv_bufsz, sock_wspace(svsk->sk_sk)); goto out_unlock; } /* Mark socket as busy. It will remain in this state until the * server has processed all pending data and put the socket back * on the idle list. */ set_bit(SK_BUSY, &svsk->sk_flags); if (!list_empty(&serv->sv_threads)) { rqstp = list_entry(serv->sv_threads.next, struct svc_rqst, rq_list); dprintk("svc: socket %p served by daemon %p\n", svsk->sk_sk, rqstp); svc_serv_dequeue(serv, rqstp); if (rqstp->rq_sock) printk(KERN_ERR "svc_sock_enqueue: server %p, rq_sock=%p!\n", rqstp, rqstp->rq_sock); rqstp->rq_sock = svsk; svsk->sk_inuse++; rqstp->rq_reserved = serv->sv_bufsz; svsk->sk_reserved += rqstp->rq_reserved; wake_up(&rqstp->rq_wait); } else {
int send(struct socket *sock, struct sockaddr_in *addr, void * data, int len) { struct msghdr msg; struct iovec iov; mm_segment_t oldfs; int size = 0; u_int32_t space; if (sock->sk==NULL) return 0; int interface=1; if(sock_setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&interface,sizeof(interface))<0) { printk(KERN_WARNING "No Broadcast"); } iov.iov_base = (char *) data; iov.iov_len = len; memset(&my_work->addr, 0, sizeof(struct sockaddr)); memset(&my_work->addr_send, 0, sizeof(struct sockaddr)); my_work->addr_send.sin_family = AF_INET; //my_work->addr_send.sin_addr.s_addr = htonl(INADDR_SEND); my_work->addr_send.sin_addr.s_addr = in_aton("255.255.255.255"); //sock->sk->sk_flags.SOCK_BROADCAST=1; my_work->addr_send.sin_port = htons(CONNECT_PORT); msg.msg_flags = 0; msg.msg_name = (void *) & my_work->addr_send; msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; if((space = sock_wspace(sock->sk))<len) { printk(KERN_INFO "ERROR"); return -ENOMEM; } sock_set_flag(my_work->sock_send,SOCK_BROADCAST); //sock->sk->broadcast=1; oldfs = get_fs(); set_fs(KERNEL_DS); size = sock_sendmsg(sock,&msg,len); if(size<0) printk(KERN_WARNING "ERROR SEND MSG:%d:",size); set_fs(oldfs); // printk(KERN_INFO MODULE_NAME":Message Sent from new program"); return size; }
/* * Any space to write? */ static inline unsigned long svc_sock_wspace(struct svc_sock *svsk) { int wspace; if (svsk->sk_sock->type == SOCK_STREAM) wspace = sk_stream_wspace(svsk->sk_sk); else wspace = sock_wspace(svsk->sk_sk); return wspace; }
int udp_ioctl(struct sock *sk, int cmd, unsigned long arg) { int err; switch(cmd) { case TIOCOUTQ: { unsigned long amount; if (sk->state == TCP_LISTEN) return(-EINVAL); amount = sock_wspace(sk); err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long)); if(err) return(err); put_fs_long(amount,(unsigned long *)arg); return(0); } case TIOCINQ: { struct sk_buff *skb; unsigned long amount; if (sk->state == TCP_LISTEN) return(-EINVAL); amount = 0; skb = skb_peek(&sk->receive_queue); if (skb != NULL) { /* * We will only return the amount * of this packet since that is all * that will be read. */ amount = skb->len-sizeof(struct udphdr); } err=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long)); if(err) return(err); put_fs_long(amount,(unsigned long *)arg); return(0); } default: return(-EINVAL); } return(0); }