diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r-- | net/ipv4/af_inet.c | 84 |
1 files changed, 66 insertions, 18 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 551ce564b035..6a1100c25a9f 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -355,6 +355,8 @@ lookup_protocol: | |||
355 | inet = inet_sk(sk); | 355 | inet = inet_sk(sk); |
356 | inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; | 356 | inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; |
357 | 357 | ||
358 | inet->nodefrag = 0; | ||
359 | |||
358 | if (SOCK_RAW == sock->type) { | 360 | if (SOCK_RAW == sock->type) { |
359 | inet->inet_num = protocol; | 361 | inet->inet_num = protocol; |
360 | if (IPPROTO_RAW == protocol) | 362 | if (IPPROTO_RAW == protocol) |
@@ -725,28 +727,31 @@ int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | |||
725 | sock_rps_record_flow(sk); | 727 | sock_rps_record_flow(sk); |
726 | 728 | ||
727 | /* We may need to bind the socket. */ | 729 | /* We may need to bind the socket. */ |
728 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 730 | if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && |
731 | inet_autobind(sk)) | ||
729 | return -EAGAIN; | 732 | return -EAGAIN; |
730 | 733 | ||
731 | return sk->sk_prot->sendmsg(iocb, sk, msg, size); | 734 | return sk->sk_prot->sendmsg(iocb, sk, msg, size); |
732 | } | 735 | } |
733 | EXPORT_SYMBOL(inet_sendmsg); | 736 | EXPORT_SYMBOL(inet_sendmsg); |
734 | 737 | ||
735 | static ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, | 738 | ssize_t inet_sendpage(struct socket *sock, struct page *page, int offset, |
736 | size_t size, int flags) | 739 | size_t size, int flags) |
737 | { | 740 | { |
738 | struct sock *sk = sock->sk; | 741 | struct sock *sk = sock->sk; |
739 | 742 | ||
740 | sock_rps_record_flow(sk); | 743 | sock_rps_record_flow(sk); |
741 | 744 | ||
742 | /* We may need to bind the socket. */ | 745 | /* We may need to bind the socket. */ |
743 | if (!inet_sk(sk)->inet_num && inet_autobind(sk)) | 746 | if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && |
747 | inet_autobind(sk)) | ||
744 | return -EAGAIN; | 748 | return -EAGAIN; |
745 | 749 | ||
746 | if (sk->sk_prot->sendpage) | 750 | if (sk->sk_prot->sendpage) |
747 | return sk->sk_prot->sendpage(sk, page, offset, size, flags); | 751 | return sk->sk_prot->sendpage(sk, page, offset, size, flags); |
748 | return sock_no_sendpage(sock, page, offset, size, flags); | 752 | return sock_no_sendpage(sock, page, offset, size, flags); |
749 | } | 753 | } |
754 | EXPORT_SYMBOL(inet_sendpage); | ||
750 | 755 | ||
751 | int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | 756 | int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, |
752 | size_t size, int flags) | 757 | size_t size, int flags) |
@@ -892,10 +897,10 @@ const struct proto_ops inet_stream_ops = { | |||
892 | .shutdown = inet_shutdown, | 897 | .shutdown = inet_shutdown, |
893 | .setsockopt = sock_common_setsockopt, | 898 | .setsockopt = sock_common_setsockopt, |
894 | .getsockopt = sock_common_getsockopt, | 899 | .getsockopt = sock_common_getsockopt, |
895 | .sendmsg = tcp_sendmsg, | 900 | .sendmsg = inet_sendmsg, |
896 | .recvmsg = inet_recvmsg, | 901 | .recvmsg = inet_recvmsg, |
897 | .mmap = sock_no_mmap, | 902 | .mmap = sock_no_mmap, |
898 | .sendpage = tcp_sendpage, | 903 | .sendpage = inet_sendpage, |
899 | .splice_read = tcp_splice_read, | 904 | .splice_read = tcp_splice_read, |
900 | #ifdef CONFIG_COMPAT | 905 | #ifdef CONFIG_COMPAT |
901 | .compat_setsockopt = compat_sock_common_setsockopt, | 906 | .compat_setsockopt = compat_sock_common_setsockopt, |
@@ -1100,7 +1105,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) | |||
1100 | if (err) | 1105 | if (err) |
1101 | return err; | 1106 | return err; |
1102 | 1107 | ||
1103 | sk_setup_caps(sk, &rt->u.dst); | 1108 | sk_setup_caps(sk, &rt->dst); |
1104 | 1109 | ||
1105 | new_saddr = rt->rt_src; | 1110 | new_saddr = rt->rt_src; |
1106 | 1111 | ||
@@ -1166,7 +1171,7 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1166 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0); | 1171 | err = ip_route_output_flow(sock_net(sk), &rt, &fl, sk, 0); |
1167 | } | 1172 | } |
1168 | if (!err) | 1173 | if (!err) |
1169 | sk_setup_caps(sk, &rt->u.dst); | 1174 | sk_setup_caps(sk, &rt->dst); |
1170 | else { | 1175 | else { |
1171 | /* Routing failed... */ | 1176 | /* Routing failed... */ |
1172 | sk->sk_route_caps = 0; | 1177 | sk->sk_route_caps = 0; |
@@ -1425,13 +1430,49 @@ unsigned long snmp_fold_field(void __percpu *mib[], int offt) | |||
1425 | } | 1430 | } |
1426 | EXPORT_SYMBOL_GPL(snmp_fold_field); | 1431 | EXPORT_SYMBOL_GPL(snmp_fold_field); |
1427 | 1432 | ||
1428 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize) | 1433 | #if BITS_PER_LONG==32 |
1434 | |||
1435 | u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset) | ||
1436 | { | ||
1437 | u64 res = 0; | ||
1438 | int cpu; | ||
1439 | |||
1440 | for_each_possible_cpu(cpu) { | ||
1441 | void *bhptr, *userptr; | ||
1442 | struct u64_stats_sync *syncp; | ||
1443 | u64 v_bh, v_user; | ||
1444 | unsigned int start; | ||
1445 | |||
1446 | /* first mib used by softirq context, we must use _bh() accessors */ | ||
1447 | bhptr = per_cpu_ptr(SNMP_STAT_BHPTR(mib), cpu); | ||
1448 | syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); | ||
1449 | do { | ||
1450 | start = u64_stats_fetch_begin_bh(syncp); | ||
1451 | v_bh = *(((u64 *) bhptr) + offt); | ||
1452 | } while (u64_stats_fetch_retry_bh(syncp, start)); | ||
1453 | |||
1454 | /* second mib used in USER context */ | ||
1455 | userptr = per_cpu_ptr(SNMP_STAT_USRPTR(mib), cpu); | ||
1456 | syncp = (struct u64_stats_sync *)(userptr + syncp_offset); | ||
1457 | do { | ||
1458 | start = u64_stats_fetch_begin(syncp); | ||
1459 | v_user = *(((u64 *) userptr) + offt); | ||
1460 | } while (u64_stats_fetch_retry(syncp, start)); | ||
1461 | |||
1462 | res += v_bh + v_user; | ||
1463 | } | ||
1464 | return res; | ||
1465 | } | ||
1466 | EXPORT_SYMBOL_GPL(snmp_fold_field64); | ||
1467 | #endif | ||
1468 | |||
1469 | int snmp_mib_init(void __percpu *ptr[2], size_t mibsize, size_t align) | ||
1429 | { | 1470 | { |
1430 | BUG_ON(ptr == NULL); | 1471 | BUG_ON(ptr == NULL); |
1431 | ptr[0] = __alloc_percpu(mibsize, __alignof__(unsigned long)); | 1472 | ptr[0] = __alloc_percpu(mibsize, align); |
1432 | if (!ptr[0]) | 1473 | if (!ptr[0]) |
1433 | goto err0; | 1474 | goto err0; |
1434 | ptr[1] = __alloc_percpu(mibsize, __alignof__(unsigned long)); | 1475 | ptr[1] = __alloc_percpu(mibsize, align); |
1435 | if (!ptr[1]) | 1476 | if (!ptr[1]) |
1436 | goto err1; | 1477 | goto err1; |
1437 | return 0; | 1478 | return 0; |
@@ -1488,25 +1529,32 @@ static const struct net_protocol icmp_protocol = { | |||
1488 | static __net_init int ipv4_mib_init_net(struct net *net) | 1529 | static __net_init int ipv4_mib_init_net(struct net *net) |
1489 | { | 1530 | { |
1490 | if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics, | 1531 | if (snmp_mib_init((void __percpu **)net->mib.tcp_statistics, |
1491 | sizeof(struct tcp_mib)) < 0) | 1532 | sizeof(struct tcp_mib), |
1533 | __alignof__(struct tcp_mib)) < 0) | ||
1492 | goto err_tcp_mib; | 1534 | goto err_tcp_mib; |
1493 | if (snmp_mib_init((void __percpu **)net->mib.ip_statistics, | 1535 | if (snmp_mib_init((void __percpu **)net->mib.ip_statistics, |
1494 | sizeof(struct ipstats_mib)) < 0) | 1536 | sizeof(struct ipstats_mib), |
1537 | __alignof__(struct ipstats_mib)) < 0) | ||
1495 | goto err_ip_mib; | 1538 | goto err_ip_mib; |
1496 | if (snmp_mib_init((void __percpu **)net->mib.net_statistics, | 1539 | if (snmp_mib_init((void __percpu **)net->mib.net_statistics, |
1497 | sizeof(struct linux_mib)) < 0) | 1540 | sizeof(struct linux_mib), |
1541 | __alignof__(struct linux_mib)) < 0) | ||
1498 | goto err_net_mib; | 1542 | goto err_net_mib; |
1499 | if (snmp_mib_init((void __percpu **)net->mib.udp_statistics, | 1543 | if (snmp_mib_init((void __percpu **)net->mib.udp_statistics, |
1500 | sizeof(struct udp_mib)) < 0) | 1544 | sizeof(struct udp_mib), |
1545 | __alignof__(struct udp_mib)) < 0) | ||
1501 | goto err_udp_mib; | 1546 | goto err_udp_mib; |
1502 | if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics, | 1547 | if (snmp_mib_init((void __percpu **)net->mib.udplite_statistics, |
1503 | sizeof(struct udp_mib)) < 0) | 1548 | sizeof(struct udp_mib), |
1549 | __alignof__(struct udp_mib)) < 0) | ||
1504 | goto err_udplite_mib; | 1550 | goto err_udplite_mib; |
1505 | if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics, | 1551 | if (snmp_mib_init((void __percpu **)net->mib.icmp_statistics, |
1506 | sizeof(struct icmp_mib)) < 0) | 1552 | sizeof(struct icmp_mib), |
1553 | __alignof__(struct icmp_mib)) < 0) | ||
1507 | goto err_icmp_mib; | 1554 | goto err_icmp_mib; |
1508 | if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics, | 1555 | if (snmp_mib_init((void __percpu **)net->mib.icmpmsg_statistics, |
1509 | sizeof(struct icmpmsg_mib)) < 0) | 1556 | sizeof(struct icmpmsg_mib), |
1557 | __alignof__(struct icmpmsg_mib)) < 0) | ||
1510 | goto err_icmpmsg_mib; | 1558 | goto err_icmpmsg_mib; |
1511 | 1559 | ||
1512 | tcp_mib_init(net); | 1560 | tcp_mib_init(net); |