网络子系统80_inet协议族-SOCK_RAW(一)
// 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; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。