📄 my_inet.c
字号:
#include <linux/net.h>#include <linux/init.h>#include <linux/module.h>#include <linux/tcp.h>#include <net/sock.h>#include <net/icmp.h>#include <net/tcp.h>#include <net/request_sock.h>#include <net/protocol.h>#include <linux/in.h>#include <net/udp.h>#include <linux/netdevice.h>#include <linux/bootmem.h>#include <linux/inetdevice.h>#include <linux/proc_fs.h>#include <linux/mroute.h>#include <net/ip_fib.h>#include <net/xfrm.h>#include <net/raw.h>#include <net/neighbour.h>#include <linux/jhash.h>#include <net/ip_mp_alg.h>#include <linux/netlink.h>#include <linux/igmp.h>#include <linux/if_arp.h>#include <linux/netfilter_arp.h>#include <linux/errqueue.h>#include <linux/netfilter_ipv4.h>#include <linux/snmp.h>#include <linux/random.h>#include <asm/unaligned.h>#include "my_inet.h"DEFINE_SNMP_STAT(struct linux_mib, mynet_statistics) __read_mostly;#define MYNET_INC_STATS_USER(field) SNMP_INC_STATS_USER(mynet_statistics, field)#define MYNET_INC_STATS_BH(field) SNMP_INC_STATS_BH(mynet_statistics, field)#define MYNET_INC_STATS(field) SNMP_INC_STATS(mynet_statistics, field)#define MYTCP_INC_STATS_BH(field) SNMP_INC_STATS_BH(mytcp_statistics, field)#define MYNET_ADD_STATS_USER(field, adnd) SNMP_ADD_STATS_USER(mynet_statistics, field, adnd)#include "myinet_hashtables.c"#include "mytcp_output.c"#include "mytcp_cong.c"#include "mytcp_input.c"#include "myinet_connection_sock.c"#include "mytcp_timer.c" #include "my_protocol.c"#include "myip_options.c"#include "myip_forward.c"#include "myfib_lookup.h"#include "myfib_semantics.c"#include "myinet_timewait_sock.c"#include "mytcp_minisocks.c"#include "my_inetpeer.c"#include "myfib_rules.c"#include "myfib_hash.c"#include "myfib_frontend.c"#include "mydevinet.c"#include "my_route.c"#include "myigmp.c"#include "myip_output.c"#include "myip_sockglue.c"#include "mydatagram.c"#include "my_udp.c"#include "my_raw.c"#include "mytcp.c"#include "mytcp_ipv4.c"#include "myicmp.c"#include "myarp.c"#include "myipmr.c"#include "myip_fragment.c"#include "myip_input.c"#include "my_systcl_net_ipv4.c"#ifdef CONFIG_IP_MULTICASTstatic struct net_protocol myigmp_protocol = { .handler = myigmp_rcv,};#endifstatic struct net_protocol mytcp_protocol = { .handler = mytcp_v4_rcv, .err_handler = mytcp_v4_err, .no_policy = 1,};static struct net_protocol myudp_protocol = { .handler = myudp_rcv, .err_handler = myudp_err, .no_policy = 1,};static struct net_protocol myicmp_protocol = { .handler = myicmp_rcv,};#ifdef INET_REFCNT_DEBUGatomic_t myinet_sock_nr;#endifvoid myinet_sock_destruct(struct sock *sk){}static int __init myinit_ipv4_mibs(void){ mynet_statistics[0] = alloc_percpu(struct linux_mib); mynet_statistics[1] = alloc_percpu(struct linux_mib); myip_statistics[0] = alloc_percpu(struct ipstats_mib); myip_statistics[1] = alloc_percpu(struct ipstats_mib); myicmp_statistics[0] = alloc_percpu(struct icmp_mib); myicmp_statistics[1] = alloc_percpu(struct icmp_mib); mytcp_statistics[0] = alloc_percpu(struct tcp_mib); mytcp_statistics[1] = alloc_percpu(struct tcp_mib); myudp_statistics[0] = alloc_percpu(struct udp_mib); myudp_statistics[1] = alloc_percpu(struct udp_mib); if (!(mynet_statistics[0] && mynet_statistics[1] && myip_statistics[0] && myip_statistics[1] && mytcp_statistics[0] && mytcp_statistics[1] && myudp_statistics[0] && myudp_statistics[1])) return -ENOMEM; SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOALGORITHM, 1); SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOMIN, TCP_RTO_MIN*1000/HZ); SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_RTOMAX, TCP_RTO_MAX*1000/HZ); SNMP_ADD_STATS_USER(mytcp_statistics, TCP_MIB_MAXCONN, -1); return 0;}static void __exit myexit_ipv4_mibs(void){ int i; for( i = 0; i < 2; i ++ ){ free_percpu( mynet_statistics[i] ); free_percpu( myip_statistics[i] ); free_percpu( myicmp_statistics[i] ); free_percpu( mytcp_statistics[i] ); free_percpu( myudp_statistics[i] ); }}static int myipv4_proc_init(void){ return 0;}int myinet_release(struct socket *sock){ struct sock *sk = sock->sk; if (sk) { long timeout; myip_mc_drop_socket(sk); timeout = 0; if (sock_flag(sk, SOCK_LINGER) && !(current->flags & PF_EXITING)) timeout = sk->sk_lingertime; sock->sk = NULL; sk->sk_prot->close(sk, timeout); } return 0;}int mysysctl_ip_nonlocal_bind;int myinet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len){ struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); unsigned short snum; int chk_addr_ret; int err; 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; chk_addr_ret = myinet_addr_type(addr->sin_addr.s_addr); err = -EADDRNOTAVAIL; if( !mysysctl_ip_nonlocal_bind && !inet->freebind && addr->sin_addr.s_addr != 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 && !capable(CAP_NET_BIND_SERVICE)) goto out; lock_sock(sk); err = -EINVAL; if (sk->sk_state != TCP_CLOSE || inet->num) goto out_release_sock; inet->rcv_saddr = inet->saddr = addr->sin_addr.s_addr; if( chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST ) inet->saddr = 0; if( sk->sk_prot->get_port(sk, snum) ){ inet->saddr = inet->rcv_saddr = 0; err = -EADDRINUSE; goto out_release_sock; } if( inet->rcv_saddr ) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; if( snum ) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; inet->sport = htons(inet->num); inet->daddr = 0; inet->dport = 0; sk_dst_reset(sk); err = 0;out_release_sock: release_sock(sk);out: return err;}static long myinet_wait_for_connect(struct sock *sk, long timeo){ DEFINE_WAIT(wait); prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); while ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); if (signal_pending(current) || !timeo) break; prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); } finish_wait(sk->sk_sleep, &wait); printk(KERN_INFO "the return value: %d\n", timeo); return timeo;}int myinet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags){ struct sock *sk = sock->sk; int err; long timeo; lock_sock(sk); if (uaddr->sa_family == AF_UNSPEC) { err = sk->sk_prot->disconnect(sk, flags); sock->state = err ? SS_DISCONNECTING : SS_UNCONNECTED; goto out; } switch (sock->state) { default: err = -EINVAL; goto out; case SS_CONNECTED: err = -EISCONN; goto out; case SS_CONNECTING: err = -EALREADY; break; case SS_UNCONNECTED: err = -EISCONN; if (sk->sk_state != TCP_CLOSE) goto out; err = sk->sk_prot->connect(sk, uaddr, addr_len); if (err < 0) goto out; sock->state = SS_CONNECTING; err = -EINPROGRESS; break; } timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); if( (1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV) ){ if (!timeo || !myinet_wait_for_connect(sk, timeo)) goto out; err = sock_intr_errno(timeo); printk(KERN_INFO "the err freom sock_intr_errno: %d\n", err ); if (signal_pending(current)) goto out; } if (sk->sk_state == TCP_CLOSE){ printk(KERN_INFO "sock state close!\n"); goto sock_error; } sock->state = SS_CONNECTED; err = 0;out: release_sock(sk); return err;sock_error: err = sock_error(sk) ? : -ECONNABORTED; sock->state = SS_UNCONNECTED; if (sk->sk_prot->disconnect(sk, flags)) sock->state = SS_DISCONNECTING; goto out;}int myinet_accept(struct socket *sock, struct socket *newsock, int flags){ struct sock *sk1 = sock->sk; int err = -EINVAL; struct sock *sk2 = sk1->sk_prot->accept(sk1, flags, &err); if (!sk2) goto do_err; lock_sock(sk2); BUG_TRAP((1 << sk2->sk_state) & (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)); sock_graft(sk2, newsock); newsock->state = SS_CONNECTED; err = 0; release_sock(sk2);do_err: return err;}int myinet_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer){ struct sock *sk = sock->sk; struct inet_sock *inet = inet_sk(sk); struct sockaddr_in *sin = (struct sockaddr_in *)uaddr; sin->sin_family = MY_AF_INET; if (peer) { if (!inet->dport || (((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_SYN_SENT)) && peer == 1)) return -ENOTCONN; sin->sin_port = inet->dport; sin->sin_addr.s_addr = inet->daddr; } else { __u32 addr = inet->rcv_saddr; if (!addr) addr = inet->saddr; sin->sin_port = inet->sport; sin->sin_addr.s_addr = addr; } memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); *uaddr_len = sizeof(*sin); return 0;}int myinet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg){ struct sock *sk = sock->sk; int err = 0; switch(cmd){ case SIOCGIFADDR: case SIOCSIFADDR: case SIOCGIFBRDADDR: case SIOCSIFBRDADDR: case SIOCGIFNETMASK: case SIOCSIFNETMASK: case SIOCGIFDSTADDR: case SIOCSIFDSTADDR: case SIOCSIFPFLAGS: case SIOCGIFPFLAGS: case SIOCSIFFLAGS: err = mydevinet_ioctl(cmd, (void __user *)arg); break; } return err;}int myinet_listen(struct socket *sock, int backlog){ struct sock *sk = sock->sk; unsigned char old_state; int err; lock_sock(sk); err = -EINVAL; if( sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM ) goto out; old_state = sk->sk_state; if (!((1 << old_state) & (TCPF_CLOSE | TCPF_LISTEN))) goto out; if (old_state != TCP_LISTEN) { err = myinet_csk_listen_start(sk, TCP_SYNQ_HSIZE); if (err) goto out; } printk(KERN_INFO "%s:%d: the backlog: %d\n", __FUNCTION__,__LINE__, backlog ); sk->sk_max_ack_backlog = backlog; err = 0;out: release_sock(sk); return err;}int myinet_shutdown(struct socket *sock, int how){ return 0;}static int myinet_autobind(struct sock *sk)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -