6-socket的实践到内核--Unix中socket的地址绑定 .
来源:互联网 发布:数据库安全管理原则 编辑:程序博客网 时间:2024/06/03 17:37
http://blog.csdn.net/embeddedfly/article/details/6411723
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
将“电话号码”赋值给“电话”,即将设定的地址结构与socket挂起钩来,朋友们以后理解指针赋值可以理解为钩子,就象网上有种叫法“钩子函数”实际就是指针函数
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
case SYS_BIND:
err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
int err, fput_needed;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
err = move_addr_to_kernel(umyaddr, addrlen, address);
if (err >= 0) {
err = security_socket_bind(sock,
(struct sockaddr *)address,
addrlen);
if (!err)
err = sock->ops->bind(sock,
(struct sockaddr *)
address, addrlen);
}
fput_light(sock->file, fput_needed);
}
return err;
}
可以看到函数首先要找到我们前边创建的socket,sockfd_lookup_light()函数需要分析一下
static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
{
struct file *file;
struct socket *sock;
*err = -EBADF;
file = fget_light(fd, fput_needed);
if (file) {
sock = sock_from_file(file, err);
if (sock)
return sock;
fput_light(file, *fput_needed);
}
return NULL;
}
static struct socket *sock_from_file(struct file *file, int *err)
{
if (file->f_op == &socket_file_ops)
return file->private_data; /* set in sock_map_fd */
*err = -ENOTSOCK;
return NULL;
}
file->private_data = sock;
int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
{
if (ulen < 0 || ulen > MAX_SOCK_ADDR)
return -EINVAL;
if (ulen == 0)
return 0;
if (copy_from_user(kaddr, uaddr, ulen))
return -EFAULT;
return audit_sockaddr(ulen, kaddr);
}
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
struct sockaddr_un {
sa_family_t sun_family; /* AF_UNIX */
char sun_path[UNIX_PATH_MAX]; /* pathname */
};
#define UNIX_PATH_MAX 108
struct unix_address {
atomic_t refcnt;
int len;
unsigned hash;
struct sockaddr_un name[0];
};
char address[MAX_SOCK_ADDR];
#define MAX_SOCK_ADDR 128
err = sock->ops->bind(sock,
(struct sockaddr *)
address, addrlen);
sock->ops = &unix_stream_ops;
static const struct proto_ops unix_stream_ops = {
.family = PF_UNIX,
.owner = THIS_MODULE,
.release = unix_release,
.bind = unix_bind,
.connect = unix_stream_connect,
.socketpair = unix_socketpair,
.accept = unix_accept,
.getname = unix_getname,
.poll = unix_poll,
.ioctl = unix_ioctl,
.listen = unix_listen,
.shutdown = unix_shutdown,
.setsockopt = sock_no_setsockopt,
.getsockopt = sock_no_getsockopt,
.sendmsg = unix_stream_sendmsg,
.recvmsg = unix_stream_recvmsg,
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
从上面的定义中我们可以看到要执行挂在钩子上的函数unix_bind()了,追踪它,这个函数在/net/unix/Af_unix.c的765行处,需要分段分析
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct net *net = sock_net(sk);
struct unix_sock *u = unix_sk(sk);
struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
struct dentry * dentry = NULL;
struct nameidata nd;
int err;
unsigned hash;
struct unix_address *addr;
struct hlist_head *list;
err = -EINVAL;
if (sunaddr->sun_family != AF_UNIX)
goto out;
if (addr_len==sizeof(short)) {
err = unix_autobind(sock);
goto out;
}
err = unix_mkname(sunaddr, addr_len, &hash);
static int unix_mkname(struct sockaddr_un * sunaddr, int len, unsigned *hashp)
{
if (len <= sizeof(short) || len > sizeof(*sunaddr))
return -EINVAL;
if (!sunaddr || sunaddr->sun_family != AF_UNIX)
return -EINVAL;
if (sunaddr->sun_path[0]) {
/*
* This may look like an off by one error but it is a bit more
* subtle. 108 is the longest valid AF_UNIX path for a binding.
* sun_path[108] doesnt as such exist. However in kernel space
* we are guaranteed that it is a valid memory location in our
* kernel address buffer.
*/
((char *)sunaddr)[len]=0;
len = strlen(sunaddr->sun_path)+1+sizeof(short);
return len;
}
*hashp = unix_hash_fold(csum_partial((char*)sunaddr, len, 0));
return len;
}
if (err < 0)
goto out;
addr_len = err;
mutex_lock(&u->readlock);
err = -EINVAL;
if (u->addr)
goto out_up;
err = -ENOMEM;
addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
if (!addr)
goto out_up;
memcpy(addr->name, sunaddr, addr_len);
addr->len = addr_len;
addr->hash = hash ^ sk->sk_type;
atomic_set(&addr->refcnt, 1);
if (sunaddr->sun_path[0]) {
unsigned int mode;
err = 0;
/*
* Get the parent directory, calculate the hash for last
* component.
*/
err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
if (err)
goto out_mknod_parent;
dentry = lookup_create(&nd, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out_mknod_unlock;
/*
* All right, let's create it.
*/
mode = S_IFSOCK |
(SOCK_INODE(sock)->i_mode & ~current->fs->umask);
err = mnt_want_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
mnt_drop_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
dput(nd.path.dentry);
nd.path.dentry = dentry;
addr->hash = UNIX_HASH_SIZE;
}
spin_lock(&unix_table_lock);
if (!sunaddr->sun_path[0]) {
err = -EADDRINUSE;
if (__unix_find_socket_byname(net, sunaddr, addr_len,
sk->sk_type, hash)) {
unix_release_addr(addr);
goto out_unlock;
}
list = &unix_socket_table[addr->hash];
} else {
list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
u->dentry = nd.path.dentry;
u->mnt = nd.path.mnt;
}
err = 0;
__unix_remove_socket(sk);
u->addr = addr;
__unix_insert_socket(list, sk);
out_unlock:
spin_unlock(&unix_table_lock);
out_up:
mutex_unlock(&u->readlock);
out:
return err;
out_mknod_dput:
dput(dentry);
out_mknod_unlock:
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
path_put(&nd.path);
out_mknod_parent:
if (err==-EEXIST)
err=-EADDRINUSE;
unix_release_addr(addr);
goto out_up;
}
- 6-socket的实践到内核--Unix中socket的地址绑定
- 6-socket的实践到内核--Unix中socket的地址绑定 .
- 5-socket的实践到内核--追踪Unix的socket
- 5-socket的实践到内核--追踪Unix的socket .
- 1--socket的实践到内核--socket实践练习
- 1--socket的实践到内核--socket实践练习 .
- 2-socket的实践到内核--socket使用IP地址通讯
- 2-socket的实践到内核--socket使用IP地址通讯 .
- 7-socket的实践到内核--socket的监听
- 14-socket的实践到内核--socket的关闭
- 7-socket的实践到内核--socket的监听 .
- 14-socket的实践到内核--socket的关闭
- 3-socket的实践到内核--追踪socket到内核
- 3-socket的实践到内核--追踪socket到内核 .
- 9-socket的实践到内核--client调用connect
- 9-socket的实践到内核--client调用connect .
- 10-socket的实践到内核--UDP的socket数据的接收
- 11-socket的实践到内核--UDP的socket数据的发送
- hadoop源码调试环境搭建
- spring 同时配置hibernate and jdbc 事务
- SQLite3使用总结备忘(多线程/WAL/锁等)
- VMWare三种工作模式
- 5-socket的实践到内核--追踪Unix的socket .
- 6-socket的实践到内核--Unix中socket的地址绑定 .
- 7-socket的实践到内核--socket的监听 .
- 8-socket的实践到内核--接受socket的连接 .
- ibatis事务处理
- document.all用法
- 大数运算
- getDeclaredMethod()和getMethod()的区别
- usb摄像头在s3c6410平台上的测试
- 类名.class, class.forName(), getClass()区别