📄 af_inet.c
字号:
}}/* * Shall we try to damage output packets if routing dev changes? */int sysctl_ip_dynaddr __read_mostly;static int inet_sk_reselect_saddr(struct sock *sk){ struct inet_sock *inet = inet_sk(sk); int err; struct rtable *rt; __be32 old_saddr = inet->saddr; __be32 new_saddr; __be32 daddr = inet->daddr; if (inet->opt && inet->opt->srr) daddr = inet->opt->faddr; /* Query new route. */ err = ip_route_connect(&rt, daddr, 0, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, sk->sk_protocol, inet->sport, inet->dport, sk, 0); if (err) return err; sk_setup_caps(sk, &rt->u.dst); new_saddr = rt->rt_src; if (new_saddr == old_saddr) return 0; if (sysctl_ip_dynaddr > 1) { printk(KERN_INFO "%s(): shifting inet->" "saddr from %d.%d.%d.%d to %d.%d.%d.%d\n", __FUNCTION__, NIPQUAD(old_saddr), NIPQUAD(new_saddr)); } inet->saddr = inet->rcv_saddr = new_saddr; /* * XXX The only one ugly spot where we need to * XXX really change the sockets identity after * XXX it has entered the hashes. -DaveM * * Besides that, it does not check for connection * uniqueness. Wait for troubles. */ __sk_prot_rehash(sk); return 0;}int inet_sk_rebuild_header(struct sock *sk){ struct inet_sock *inet = inet_sk(sk); struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); __be32 daddr; int err; /* Route is OK, nothing to do. */ if (rt) return 0; /* Reroute. */ daddr = inet->daddr; if (inet->opt && inet->opt->srr) daddr = inet->opt->faddr;{ struct flowi fl = { .oif = sk->sk_bound_dev_if, .nl_u = { .ip4_u = { .daddr = daddr, .saddr = inet->saddr, .tos = RT_CONN_FLAGS(sk), }, }, .proto = sk->sk_protocol, .uli_u = { .ports = { .sport = inet->sport, .dport = inet->dport, }, }, }; security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, 0);} if (!err) sk_setup_caps(sk, &rt->u.dst); else { /* Routing failed... */ sk->sk_route_caps = 0; /* * Other protocols have to map its equivalent state to TCP_SYN_SENT. * DCCP maps its DCCP_REQUESTING state to TCP_SYN_SENT. -acme */ if (!sysctl_ip_dynaddr || sk->sk_state != TCP_SYN_SENT || (sk->sk_userlocks & SOCK_BINDADDR_LOCK) || (err = inet_sk_reselect_saddr(sk)) != 0) sk->sk_err_soft = -err; } return err;}EXPORT_SYMBOL(inet_sk_rebuild_header);static int inet_gso_send_check(struct sk_buff *skb){ struct iphdr *iph; struct net_protocol *ops; int proto; int ihl; int err = -EINVAL; if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) goto out; iph = ip_hdr(skb); ihl = iph->ihl * 4; if (ihl < sizeof(*iph)) goto out; if (unlikely(!pskb_may_pull(skb, ihl))) goto out; __skb_pull(skb, ihl); skb_reset_transport_header(skb); iph = ip_hdr(skb); proto = iph->protocol & (MAX_INET_PROTOS - 1); err = -EPROTONOSUPPORT; rcu_read_lock(); ops = rcu_dereference(inet_protos[proto]); if (likely(ops && ops->gso_send_check)) err = ops->gso_send_check(skb); rcu_read_unlock();out: return err;}static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features){ struct sk_buff *segs = ERR_PTR(-EINVAL); struct iphdr *iph; struct net_protocol *ops; int proto; int ihl; int id; if (!(features & NETIF_F_V4_CSUM)) features &= ~NETIF_F_SG; if (unlikely(skb_shinfo(skb)->gso_type & ~(SKB_GSO_TCPV4 | SKB_GSO_UDP | SKB_GSO_DODGY | SKB_GSO_TCP_ECN | 0))) goto out; if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) goto out; iph = ip_hdr(skb); ihl = iph->ihl * 4; if (ihl < sizeof(*iph)) goto out; if (unlikely(!pskb_may_pull(skb, ihl))) goto out; __skb_pull(skb, ihl); skb_reset_transport_header(skb); iph = ip_hdr(skb); id = ntohs(iph->id); proto = iph->protocol & (MAX_INET_PROTOS - 1); segs = ERR_PTR(-EPROTONOSUPPORT); rcu_read_lock(); ops = rcu_dereference(inet_protos[proto]); if (likely(ops && ops->gso_segment)) segs = ops->gso_segment(skb, features); rcu_read_unlock(); if (!segs || unlikely(IS_ERR(segs))) goto out; skb = segs; do { iph = ip_hdr(skb); iph->id = htons(id++); iph->tot_len = htons(skb->len - skb->mac_len); iph->check = 0; iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl); } while ((skb = skb->next));out: return segs;}unsigned long snmp_fold_field(void *mib[], int offt){ unsigned long res = 0; int i; for_each_possible_cpu(i) { res += *(((unsigned long *) per_cpu_ptr(mib[0], i)) + offt); res += *(((unsigned long *) per_cpu_ptr(mib[1], i)) + offt); } return res;}EXPORT_SYMBOL_GPL(snmp_fold_field);int snmp_mib_init(void *ptr[2], size_t mibsize, size_t mibalign){ BUG_ON(ptr == NULL); ptr[0] = __alloc_percpu(mibsize); if (!ptr[0]) goto err0; ptr[1] = __alloc_percpu(mibsize); if (!ptr[1]) goto err1; return 0;err1: free_percpu(ptr[0]); ptr[0] = NULL;err0: return -ENOMEM;}EXPORT_SYMBOL_GPL(snmp_mib_init);void snmp_mib_free(void *ptr[2]){ BUG_ON(ptr == NULL); free_percpu(ptr[0]); free_percpu(ptr[1]); ptr[0] = ptr[1] = NULL;}EXPORT_SYMBOL_GPL(snmp_mib_free);#ifdef CONFIG_IP_MULTICASTstatic struct net_protocol igmp_protocol = { .handler = igmp_rcv,};#endifstatic struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .gso_send_check = tcp_v4_gso_send_check, .gso_segment = tcp_tso_segment, .no_policy = 1,};static struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, .no_policy = 1,};static struct net_protocol icmp_protocol = { .handler = icmp_rcv,};static int __init init_ipv4_mibs(void){ if (snmp_mib_init((void **)net_statistics, sizeof(struct linux_mib), __alignof__(struct linux_mib)) < 0) goto err_net_mib; if (snmp_mib_init((void **)ip_statistics, sizeof(struct ipstats_mib), __alignof__(struct ipstats_mib)) < 0) goto err_ip_mib; if (snmp_mib_init((void **)icmp_statistics, sizeof(struct icmp_mib), __alignof__(struct icmp_mib)) < 0) goto err_icmp_mib; if (snmp_mib_init((void **)icmpmsg_statistics, sizeof(struct icmpmsg_mib), __alignof__(struct icmpmsg_mib)) < 0) goto err_icmpmsg_mib; if (snmp_mib_init((void **)tcp_statistics, sizeof(struct tcp_mib), __alignof__(struct tcp_mib)) < 0) goto err_tcp_mib; if (snmp_mib_init((void **)udp_statistics, sizeof(struct udp_mib), __alignof__(struct udp_mib)) < 0) goto err_udp_mib; if (snmp_mib_init((void **)udplite_statistics, sizeof(struct udp_mib), __alignof__(struct udp_mib)) < 0) goto err_udplite_mib; tcp_mib_init(); return 0;err_udplite_mib: snmp_mib_free((void **)udp_statistics);err_udp_mib: snmp_mib_free((void **)tcp_statistics);err_tcp_mib: snmp_mib_free((void **)icmpmsg_statistics);err_icmpmsg_mib: snmp_mib_free((void **)icmp_statistics);err_icmp_mib: snmp_mib_free((void **)ip_statistics);err_ip_mib: snmp_mib_free((void **)net_statistics);err_net_mib: return -ENOMEM;}static int ipv4_proc_init(void);/* * IP protocol layer initialiser */static struct packet_type ip_packet_type = { .type = __constant_htons(ETH_P_IP), .func = ip_rcv, .gso_send_check = inet_gso_send_check, .gso_segment = inet_gso_segment,};static int __init inet_init(void){ struct sk_buff *dummy_skb; struct inet_protosw *q; struct list_head *r; int rc = -EINVAL; BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); rc = proto_register(&tcp_prot, 1); if (rc) goto out; rc = proto_register(&udp_prot, 1); if (rc) goto out_unregister_tcp_proto; rc = proto_register(&raw_prot, 1); if (rc) goto out_unregister_udp_proto; /* * Tell SOCKET that we are alive... */ (void)sock_register(&inet_family_ops); /* * Add all the base protocols. */ if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n"); if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n"); if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n");#ifdef CONFIG_IP_MULTICAST if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n");#endif /* Register the socket-side information for inet_create. */ for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) INIT_LIST_HEAD(r); for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) inet_register_protosw(q); /* * Set the ARP module up */ arp_init(); /* * Set the IP module up */ ip_init(); tcp_v4_init(&inet_family_ops); /* Setup TCP slab cache for open requests. */ tcp_init(); /* Add UDP-Lite (RFC 3828) */ udplite4_register(); /* * Set the ICMP layer up */ icmp_init(&inet_family_ops); /* * Initialise the multicast router */#if defined(CONFIG_IP_MROUTE) ip_mr_init();#endif /* * Initialise per-cpu ipv4 mibs */ if (init_ipv4_mibs()) printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ; ipv4_proc_init(); ipfrag_init(); dev_add_pack(&ip_packet_type); rc = 0;out: return rc;out_unregister_udp_proto: proto_unregister(&udp_prot);out_unregister_tcp_proto: proto_unregister(&tcp_prot); goto out;}fs_initcall(inet_init);/* ------------------------------------------------------------------------ */#ifdef CONFIG_PROC_FSstatic int __init ipv4_proc_init(void){ int rc = 0; if (raw_proc_init()) goto out_raw; if (tcp4_proc_init()) goto out_tcp; if (udp4_proc_init()) goto out_udp; if (fib_proc_init()) goto out_fib; if (ip_misc_proc_init()) goto out_misc;out: return rc;out_misc: fib_proc_exit();out_fib: udp4_proc_exit();out_udp: tcp4_proc_exit();out_tcp: raw_proc_exit();out_raw: rc = -ENOMEM; goto out;}#else /* CONFIG_PROC_FS */static int __init ipv4_proc_init(void){ return 0;}#endif /* CONFIG_PROC_FS */MODULE_ALIAS_NETPROTO(PF_INET);EXPORT_SYMBOL(inet_accept);EXPORT_SYMBOL(inet_bind);EXPORT_SYMBOL(inet_dgram_connect);EXPORT_SYMBOL(inet_dgram_ops);EXPORT_SYMBOL(inet_getname);EXPORT_SYMBOL(inet_ioctl);EXPORT_SYMBOL(inet_listen);EXPORT_SYMBOL(inet_register_protosw);EXPORT_SYMBOL(inet_release);EXPORT_SYMBOL(inet_sendmsg);EXPORT_SYMBOL(inet_shutdown);EXPORT_SYMBOL(inet_sock_destruct);EXPORT_SYMBOL(inet_stream_connect);EXPORT_SYMBOL(inet_stream_ops);EXPORT_SYMBOL(inet_unregister_protosw);EXPORT_SYMBOL(net_statistics);EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -