📄 sock.c
字号:
n->protocol = htons(ETH_P_IP); n->pkt_type = PACKET_HOST;#endif#ifdef LINUX_21 n->nh.raw=n->data; memset(&(IPCB(n)->opt), 0, sizeof(IPCB(n)->opt));#else n->h.iph=(struct iphdr *)n->data; memset(n->proto_priv, 0, sizeof(struct options));#endif n->ip_summed = 0; /* this prints nonsense for non-IP packets. Ignore that. */ dprintk(DEB_INP, (KERN_INFO "%s: real src %s dst %s len %d\n", n->dev->name, cipe_ntoa(saddr(n)), cipe_ntoa(daddr(n)), length));#ifdef DEBUG if (cipe_debug&DEB_PKIN) cipe_dump_packet("decrypted", n, 1);#ifdef LINUX_23 dprintk(DEB_INP, (KERN_DEBUG "%s state=%ld refcnt=%d\n", n->dev->name, n->dev->state, atomic_read(&n->dev->refcnt)));#endif#endif nf_conntrack_null(skb); /* requeue */ netif_rx(n);#ifdef LINUX_24 /* raise a softirq to process the new packet asap */ do_softirq();#endif#ifdef LINUX_21 c->stat.rx_bytes+=skb->len; /* count carrier-level bytes */#endif c->stat.rx_packets++; return NULL; framerr: ++c->stat.rx_frame_errors; /* slightly abuse this */ error: ++c->stat.rx_errors; if (n) kfreeskb(n, FREE_READ); return NULL;}/* Receive message. If encrypted, put it through the mill. If decrypted, return it as key exchange block. This is mostly from net/ipv4/udp.c, but cipe_decrypt_skb pulls the UDP header.*/int cipe_recvmsg(#ifdef LINUX_25 struct kiocb *iocb,#endif struct sock *sk, struct msghdr *msg#ifdef LINUX_25 , size_t len#else , int len#endif , int noblock, int flags,int *addr_len){ int copied; struct sk_buff *skb, *skn; int er=0; struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name; SOCKTOC("cipe_recvmsg",sk,c); /* * Check any passed addresses */ if (addr_len) *addr_len=sizeof(*sin); /* * From here the generic datagram does a lot of the work. Come * the finished NET3, it will do _ALL_ the work! */ do { /* CIPE: look if the packet is encrypted, repeat until a decrypted one is found */ skn=NULL; skb=skb_recv_datagram(sk,flags,noblock,&er); if(skb==NULL) { dprintk(DEB_KXC, (KERN_INFO "%s: skb_recv_datagram: %d\n", c->dev->name, er)); return er; } if (!skb->h.uh->source) { /* Synthetic KXC packets are marked by source port 0. Correct this - we know the truth from our structure. Perhaps it would be better to not correct it so the user level daemon can spot the difference? */ skb->h.uh->source=c->peerport; skb_pull(skb, sizeof(struct udphdr)); break; } skn=cipe_decrypt_skb(c, sk, skb, &(msg->msg_flags)); skb_free_datagram(sk, skb); skb=skn; } while (skb==NULL); dprintk(DEB_INP, (KERN_INFO "%s: returning " FLEN " flags %04x\n", c->dev->name, skb->len, msg->msg_flags)); copied = skb->len; if (copied > len) { copied = len;#ifdef LINUX_21 msg->msg_flags |= MSG_TRUNC;#endif } if (copied<=0) { printk(KERN_ERR "cipe_recvmsg: bogus length %d\n", copied); goto out_free; } /* * FIXME : should use udp header size info value */#ifdef LINUX_21 er = memcpy_toiovec(msg->msg_iov, skb->data, copied); if (er<0) goto out_free;#else memcpy_toiovec(msg->msg_iov, skb->data, copied);#endif sk->sk_stamp=skb->stamp; /* Copy the address. */ if (sin#ifdef LINUX_21 && skb->nh.iph /* Fake KXC has no address */#endif ) { sin->sin_family = AF_INET; sin->sin_port = skb->h.uh->source; sin->sin_addr.s_addr = daddr(skb); } er=copied; out_free: if (skb==skn) /* the buffer was a copy made by decryption */ kfreeskb(skb, FREE_READ); else skb_free_datagram(sk, skb); return(er);}#ifdef LINUX_21#include <linux/file.h>int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm){ struct file *file; struct inode *inode; struct socket *sock; struct sock *sk;#if 0 struct in_device *indev;#endif struct cipe *c0; DEVTOCIPE(dev,c,-ENODEV); if (c->sock) return -EBUSY; if (!(file=fget(parm->fd))) return(-EBADF); inode = file->f_dentry->d_inode; if (!inode || !inode->i_sock || !(sock=SOCKET_I(inode))) { fput(file); return(-ENOTSOCK); } if (sock->file != file) { printk(KERN_ERR DEVNAME ": socki_lookup: socket file changed!\n"); sock->file = file; } fput(file); if (sock->type!=SOCK_DGRAM) return(-ESOCKTNOSUPPORT); if (sock->ops->family!=AF_INET) return(-EAFNOSUPPORT); sk=sock->sk; if (sk->sk_state!=TCP_ESTABLISHED) return(-ENOTCONN); if (((c0=(struct cipe *)sk->sk_user_data)) && (c0->magic==CIPE_MAGIC)) return(-EBUSY); /* socket is already attached */ if (!cipe_use_module()) return(-ENODEV); c->owner=current->pid;#ifdef LINUX_25 c->sock=(struct inet_sock*)sk;#else c->sock=sk;#endif c->peeraddr=inet_sk(sk)->daddr; c->peerport=inet_sk(sk)->dport; c->myaddr=inet_sk(sk)->saddr; if (c->flags&CIPF_MAY_DYNIP) inet_sk(sk)->rcv_saddr=0; c->myport=htons(inet_sk(sk)->num); /* Disconnect socket, we might receive from somewhere else */ inet_sk(sk)->daddr=0; inet_sk(sk)->dport=0; /* Fill an otherwise unused field in the sock struct with this info. This field is conveniently named and the kernel uses it only for RPC. */ sk->sk_user_data=c; sk->sk_no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1; /* Set up new socket operations */ c->udp_prot=sk->sk_prot; c->cipe_proto=*sk->sk_prot; c->cipe_proto.close=cipe_sock_close; c->cipe_proto.sendmsg=cipe_sendmsg; c->cipe_proto.recvmsg=cipe_recvmsg; sk->sk_prot=&c->cipe_proto;#if 0 /* (Try to) Set our dummy hardware address from the IP address. */ /* This does not work, because the IP address is set _after_ the attach... */ if ((indev=dev->ip_ptr)) { struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; for (ifap=&indev->ifa_list; (ifa=*ifap) != NULL; ifap=&ifa->ifa_next) if (strcmp(dev->name, ifa->ifa_label) == 0) break; if (ifa) { char *x=(char *)&ifa->ifa_local; dev->dev_addr[3]=x[1]|0x80; dev->dev_addr[4]=x[2]; dev->dev_addr[5]=x[3]; } }#endif return(0);}#else /* LINUX_21 */#define sreturn(x) {sti(); return((x));}int cipe_attach(struct NET_DEVICE *dev, struct siocsifcipatt *parm){ struct file *file; struct inode *inode; struct socket *sock; struct sock *sk; int fd=parm->fd; struct cipe *c0; DEVTOCIPE(dev,c,-ENODEV); cli(); if (c->sock) sreturn(-EBUSY); if (!c->cipher) sreturn(-ENXIO); /* Find the socket (from net/socket.c) */ if (fd < 0 || fd >= NR_OPEN || !(file = current->files->fd[fd])) sreturn(-EBADF); inode = file->f_inode; if (!inode || !inode->i_sock) sreturn(-ENOTSOCK); sock=&inode->u.socket_i; if (sock->type!=SOCK_DGRAM) sreturn(-ESOCKTNOSUPPORT); if (sock->ops->family!=AF_INET) sreturn(-EAFNOSUPPORT); sk=(struct sock *)sock->data; if (sk->state!=TCP_ESTABLISHED) sreturn(-ENOTCONN); if (((c0=(struct cipe *)sk->protinfo.af_packet.bound_dev)) && (c0->magic==CIPE_MAGIC)) sreturn(-EBUSY); /* socket is already attached */ cipe_use_module(); /* cannot fail under 2.0 */ c->owner=current->pid; c->sock=sk; c->peeraddr=sk->daddr; c->peerport=sk->dummy_th.dest; c->myaddr=sk->saddr; if (c->flags&CIPF_MAY_DYNIP) sk->rcv_saddr=0; c->myport=sk->dummy_th.source; /* Disconnect socket, we might receive from somewhere else */ sk->daddr=0; sk->dummy_th.dest=0; /* Set up new socket operations */ c->udp_prot=sk->prot; c->cipe_proto=*sk->prot; c->cipe_proto.close=cipe_sock_close; c->cipe_proto.sendmsg=cipe_sendmsg; c->cipe_proto.recvmsg=cipe_recvmsg; sk->prot=&c->cipe_proto; /* Fill an otherwise unused field in the sock struct with this info. Actually, this is very similar to a packet socket! The ugly cast saves us one deref in the actual ops */ sk->protinfo.af_packet.bound_dev=(struct NET_DEVICE *)c; sk->no_check=(c->flags&CIPF_DO_CSUM) ? 0 : 1; sti(); return 0;}#endif/* Build and enqueue a fake UDP packet to receive. Note that these are neither encrypted nor SOCKSed.*/void cipe_fakenkey(struct cipe *c, char typ){ int len=sizeof(struct udphdr)+KEYXCHGBLKMIN; struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC); if (!skb) { printk(KERN_WARNING "%s: cipe_fakenkey: out of memory\n", c->dev->name); return; /* not much we can do */ } dprintk(DEB_KXC, (KERN_INFO "%s: fake kxc block typ=%d\n", c->dev->name, typ)); skb->sk=NULL; skb->dev=c->dev; skb->h.uh=(struct udphdr *)skb->data; skb->len=len;#ifdef LINUX_21 skb->nh.iph=NULL;#else saddr(skb)=c->myaddr; daddr(skb)=c->peeraddr; skb->free=1; /* Discard after use */ skb->ip_hdr=NULL;#endif skb->h.uh->source=0; /* mark as KXC packet */ skb->h.uh->dest=c->myport; len-=sizeof(struct udphdr); skb->h.uh->len=htons(len); skb->h.uh->check=0; skb->mac.raw=skb->data; /* no hardware header */ /* All those contortions for just one byte of payload data. Since we generate only NK_RREQ and NK_REQ it's effectively one _bit_... */ skb->data[sizeof(struct udphdr)]=typ; (*(__u32 *)(skb->data+sizeof(struct udphdr)+KEYXCHGTSPOS))= htonl(CURRENT_TIME_SEC); /* even need timestamp */ if (sock_queue_rcv_skb(SOCK(c), skb)<0) { printk(KERN_WARNING "%s: cipe_fakenkey: enqueuing failed\n", c->dev->name); kfreeskb(skb, FREE_WRITE); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -