套接字之 getsockname && getpeername
getsockname-获取本地地址;比如,在绑定的时候设置端口号为0由系统自动选择端口绑定,或者使用了INADDR_ANY通配所有地址的情况下,后面需要用到具体的地址和端口,就可以用getsockname获取地址信息;
getpeername-获取建立连接的对端的地址和端口;
下面为源码分析:
1 /* 2 * Get the local address ('name') of a socket object. Move the obtained 3 * name to user space. 4 */ 5 6 SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr, 7 int __user *, usockaddr_len) 8 { 9 struct socket *sock; 10 struct sockaddr_storage address; 11 int len, err, fput_needed; 12 13 /* 查找socket */ 14 sock = sockfd_lookup_light(fd, &err, &fput_needed); 15 if (!sock) 16 goto out; 17 18 err = security_socket_getsockname(sock); 19 if (err) 20 goto out_put; 21 22 /* 调用socket操作的getname函数 */ 23 err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0); 24 if (err) 25 goto out_put; 26 27 /* 拷贝地址到用户空间 */ 28 err = move_addr_to_user(&address, len, usockaddr, usockaddr_len); 29 30 out_put: 31 fput_light(sock->file, fput_needed); 32 out: 33 return err; 34 }
1 /* 2 * Get the remote address ('name') of a socket object. Move the obtained 3 * name to user space. 4 */ 5 6 SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr, 7 int __user *, usockaddr_len) 8 { 9 struct socket *sock; 10 struct sockaddr_storage address; 11 int len, err, fput_needed; 12 13 /* 查找socket */ 14 sock = sockfd_lookup_light(fd, &err, &fput_needed); 15 if (sock != NULL) { 16 err = security_socket_getpeername(sock); 17 if (err) { 18 fput_light(sock->file, fput_needed); 19 return err; 20 } 21 22 /* 调用socket操作的getname获取对端地址,此时最后一个参数为1 */ 23 err = 24 sock->ops->getname(sock, (struct sockaddr *)&address, &len, 25 1); 26 27 /* 将地址拷贝到用户空间 */ 28 if (!err) 29 err = move_addr_to_user(&address, len, usockaddr, 30 usockaddr_len); 31 fput_light(sock->file, fput_needed); 32 } 33 return err; 34 }
ipv4情况下,getsockname和getpeername都会调用下面的inet_getname函数;
1 /* 2 * This does both peername and sockname. 3 */ 4 int inet_getname(struct socket *sock, struct sockaddr *uaddr, 5 int *uaddr_len, int peer) 6 { 7 struct sock *sk = sock->sk; 8 struct inet_sock *inet = inet_sk(sk); 9 DECLARE_SOCKADDR(struct sockaddr_in *, sin, uaddr); 10 11 /* 设置地址族 */ 12 sin->sin_family = AF_INET; 13 14 /* 获取对端地址 */ 15 if (peer) { 16 /* 目的端口为空或者为未连接状态 */ 17 if (!inet->inet_dport || 18 (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && 19 peer == 1)) 20 return -ENOTCONN; 21 /* 设置目的端口和地址 */ 22 sin->sin_port = inet->inet_dport; 23 sin->sin_addr.s_addr = inet->inet_daddr; 24 } 25 /* 获取本地地址 */ 26 else { 27 /* 获取接收时ip */ 28 __be32 addr = inet->inet_rcv_saddr; 29 30 /* 不存在则获取发送时ip */ 31 if (!addr) 32 addr = inet->inet_saddr; 33 34 /* 设置端口和地址 */ 35 sin->sin_port = inet->inet_sport; 36 sin->sin_addr.s_addr = addr; 37 } 38 39 /* 填充部分 */ 40 memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); 41 42 /* 设置地址长度 */ 43 *uaddr_len = sizeof(*sin); 44 return 0; 45 }