// SOCK_RAW
1.1 static struct inet_protosw inetsw_array[] =
{
...
{
.type = SOCK_RAW,
.protocol = IPPROTO_IP, /* 通配符 */
.prot = &raw_prot, /* Networking protocol blocks attached to sockets */
.ops = &inet_sockraw_ops,
.no_check = UDP_CSUM_DEFAULT,
.flags = INET_PROTOSW_REUSE,
}
...
}
// struct socket->ops字段
2.1 static const struct proto_ops inet_sockraw_ops = {
.family = PF_INET,
.owner = THIS_MODULE,
.release = inet_release,
.bind = inet_bind,
.connect = inet_dgram_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = inet_getname,
.poll = datagram_poll,
.ioctl = inet_ioctl,
.listen = sock_no_listen,
.shutdown = inet_shutdown,
.setsockopt = sock_common_setsockopt,
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.mmap = sock_no_mmap,
.sendpage = inet_sendpage,
};
// sock绑定地址
// inet_sock->inet_rcv_saddr - Bound local ipv4 addr
// inet_sock->inet_num - Local port
// 步骤:
// 1.安全性检查
// 1.1 地址长度是否足够
// 1.2 地址类型是否正确
// 1.3 端口是否已经被占用
// 2.设置inet_sock结构的源地址和源端口
3.1 int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
//inet使用sockaddr_in
struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
struct sock *sk = sock->sk;
//inet使用inet_sock
struct inet_sock *inet = inet_sk(sk);
struct net *net = sock_net(sk);
unsigned short snum;
int chk_addr_ret;
int err;
//调用sock提供的bind
if (sk->sk_prot->bind) {
err = sk->sk_prot->bind(sk, uaddr, addr_len);
goto out;
}
err = -EINVAL;
//地址长度
if (addr_len < sizeof(struct sockaddr_in))
goto out;
//兼容性检查
if (addr->sin_family != AF_INET) {
err = -EAFNOSUPPORT;
if (addr->sin_family != AF_UNSPEC ||
addr->sin_addr.s_addr != htonl(INADDR_ANY))
goto out;
}
//检查地址类型
chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
err = -EADDRNOTAVAIL;
if (!sysctl_ip_nonlocal_bind &&
!(inet->freebind || inet->transparent) &&
addr->sin_addr.s_addr != htonl(INADDR_ANY) &&
chk_addr_ret != RTN_LOCAL &&
chk_addr_ret != RTN_MULTICAST &&
chk_addr_ret != RTN_BROADCAST)
goto out;
//端口号检查
snum = ntohs(addr->sin_port);
err = -EACCES;
if (snum && snum < PROT_SOCK &&
!ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
goto out;
lock_sock(sk);
err = -EINVAL;
//二次绑定
if (sk->sk_state != TCP_CLOSE || inet->inet_num)
goto out_release_sock;
//绑定地址
inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr;
//检查端口是否已经被绑定
if (sk->sk_prot->get_port(sk, snum)) {
inet->inet_saddr = inet->inet_rcv_saddr = 0;
err = -EADDRINUSE;
goto out_release_sock;
}
if (inet->inet_rcv_saddr)
sk->sk_userlocks |= SOCK_BINDADDR_LOCK;
if (snum)
sk->sk_userlocks |= SOCK_BINDPORT_LOCK;
//绑定端口
inet->inet_sport = htons(inet->inet_num);
inet->inet_daddr = 0;
inet->inet_dport = 0;
sk_dst_reset(sk);
err = 0;
out_release_sock:
release_sock(sk);
out:
return err;
}
// 发送数据
// 统计流量,绑定端口,由prot完成数据发送
3.2 int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size)
{
struct sock *sk = sock->sk;
//统计sock的流量
sock_rps_record_flow(sk);
//绑定port
if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind &&
inet_autobind(sk))
return -EAGAIN;
//通过prot->sendmsg发送数据
return sk->sk_prot->sendmsg(iocb, sk, msg, size);
}
// 接收数据
// 统计流量,由prot完成数据接收
3.3 int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size, int flags)
{
struct sock *sk = sock->sk;
int addr_len = 0;
int err;
//统计sock流量
sock_rps_record_flow(sk);
//通过prot->recvmsg接收数据
err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
flags & ~MSG_DONTWAIT, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
}
网络子系统80_inet协议族-SOCK_RAW(一),布布扣,bubuko.com
网络子系统80_inet协议族-SOCK_RAW(一)