diff options
Diffstat (limited to 'net/ipv4/af_inet.c')
| -rw-r--r-- | net/ipv4/af_inet.c | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 766c59658563..24b384b7903e 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -346,7 +346,8 @@ lookup_protocol: | |||
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | err = -EPERM; | 348 | err = -EPERM; |
| 349 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) | 349 | if (sock->type == SOCK_RAW && !kern && |
| 350 | !ns_capable(net->user_ns, CAP_NET_RAW)) | ||
| 350 | goto out_rcu_unlock; | 351 | goto out_rcu_unlock; |
| 351 | 352 | ||
| 352 | err = -EAFNOSUPPORT; | 353 | err = -EAFNOSUPPORT; |
| @@ -473,6 +474,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 473 | struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; | 474 | struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; |
| 474 | struct sock *sk = sock->sk; | 475 | struct sock *sk = sock->sk; |
| 475 | struct inet_sock *inet = inet_sk(sk); | 476 | struct inet_sock *inet = inet_sk(sk); |
| 477 | struct net *net = sock_net(sk); | ||
| 476 | unsigned short snum; | 478 | unsigned short snum; |
| 477 | int chk_addr_ret; | 479 | int chk_addr_ret; |
| 478 | int err; | 480 | int err; |
| @@ -496,7 +498,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 496 | goto out; | 498 | goto out; |
| 497 | } | 499 | } |
| 498 | 500 | ||
| 499 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); | 501 | chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr); |
| 500 | 502 | ||
| 501 | /* Not specified by any standard per-se, however it breaks too | 503 | /* Not specified by any standard per-se, however it breaks too |
| 502 | * many applications when removed. It is unfortunate since | 504 | * many applications when removed. It is unfortunate since |
| @@ -516,7 +518,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 516 | 518 | ||
| 517 | snum = ntohs(addr->sin_port); | 519 | snum = ntohs(addr->sin_port); |
| 518 | err = -EACCES; | 520 | err = -EACCES; |
| 519 | if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE)) | 521 | if (snum && snum < PROT_SOCK && |
| 522 | !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) | ||
| 520 | goto out; | 523 | goto out; |
| 521 | 524 | ||
| 522 | /* We keep a pair of addresses. rcv_saddr is the one | 525 | /* We keep a pair of addresses. rcv_saddr is the one |
| @@ -1251,7 +1254,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); | |||
| 1251 | 1254 | ||
| 1252 | static int inet_gso_send_check(struct sk_buff *skb) | 1255 | static int inet_gso_send_check(struct sk_buff *skb) |
| 1253 | { | 1256 | { |
| 1254 | const struct net_protocol *ops; | 1257 | const struct net_offload *ops; |
| 1255 | const struct iphdr *iph; | 1258 | const struct iphdr *iph; |
| 1256 | int proto; | 1259 | int proto; |
| 1257 | int ihl; | 1260 | int ihl; |
| @@ -1275,9 +1278,9 @@ static int inet_gso_send_check(struct sk_buff *skb) | |||
| 1275 | err = -EPROTONOSUPPORT; | 1278 | err = -EPROTONOSUPPORT; |
| 1276 | 1279 | ||
| 1277 | rcu_read_lock(); | 1280 | rcu_read_lock(); |
| 1278 | ops = rcu_dereference(inet_protos[proto]); | 1281 | ops = rcu_dereference(inet_offloads[proto]); |
| 1279 | if (likely(ops && ops->gso_send_check)) | 1282 | if (likely(ops && ops->callbacks.gso_send_check)) |
| 1280 | err = ops->gso_send_check(skb); | 1283 | err = ops->callbacks.gso_send_check(skb); |
| 1281 | rcu_read_unlock(); | 1284 | rcu_read_unlock(); |
| 1282 | 1285 | ||
| 1283 | out: | 1286 | out: |
| @@ -1288,7 +1291,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
| 1288 | netdev_features_t features) | 1291 | netdev_features_t features) |
| 1289 | { | 1292 | { |
| 1290 | struct sk_buff *segs = ERR_PTR(-EINVAL); | 1293 | struct sk_buff *segs = ERR_PTR(-EINVAL); |
| 1291 | const struct net_protocol *ops; | 1294 | const struct net_offload *ops; |
| 1292 | struct iphdr *iph; | 1295 | struct iphdr *iph; |
| 1293 | int proto; | 1296 | int proto; |
| 1294 | int ihl; | 1297 | int ihl; |
| @@ -1325,9 +1328,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
| 1325 | segs = ERR_PTR(-EPROTONOSUPPORT); | 1328 | segs = ERR_PTR(-EPROTONOSUPPORT); |
| 1326 | 1329 | ||
| 1327 | rcu_read_lock(); | 1330 | rcu_read_lock(); |
| 1328 | ops = rcu_dereference(inet_protos[proto]); | 1331 | ops = rcu_dereference(inet_offloads[proto]); |
| 1329 | if (likely(ops && ops->gso_segment)) | 1332 | if (likely(ops && ops->callbacks.gso_segment)) |
| 1330 | segs = ops->gso_segment(skb, features); | 1333 | segs = ops->callbacks.gso_segment(skb, features); |
| 1331 | rcu_read_unlock(); | 1334 | rcu_read_unlock(); |
| 1332 | 1335 | ||
| 1333 | if (!segs || IS_ERR(segs)) | 1336 | if (!segs || IS_ERR(segs)) |
| @@ -1356,7 +1359,7 @@ out: | |||
| 1356 | static struct sk_buff **inet_gro_receive(struct sk_buff **head, | 1359 | static struct sk_buff **inet_gro_receive(struct sk_buff **head, |
| 1357 | struct sk_buff *skb) | 1360 | struct sk_buff *skb) |
| 1358 | { | 1361 | { |
| 1359 | const struct net_protocol *ops; | 1362 | const struct net_offload *ops; |
| 1360 | struct sk_buff **pp = NULL; | 1363 | struct sk_buff **pp = NULL; |
| 1361 | struct sk_buff *p; | 1364 | struct sk_buff *p; |
| 1362 | const struct iphdr *iph; | 1365 | const struct iphdr *iph; |
| @@ -1378,8 +1381,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
| 1378 | proto = iph->protocol; | 1381 | proto = iph->protocol; |
| 1379 | 1382 | ||
| 1380 | rcu_read_lock(); | 1383 | rcu_read_lock(); |
| 1381 | ops = rcu_dereference(inet_protos[proto]); | 1384 | ops = rcu_dereference(inet_offloads[proto]); |
| 1382 | if (!ops || !ops->gro_receive) | 1385 | if (!ops || !ops->callbacks.gro_receive) |
| 1383 | goto out_unlock; | 1386 | goto out_unlock; |
| 1384 | 1387 | ||
| 1385 | if (*(u8 *)iph != 0x45) | 1388 | if (*(u8 *)iph != 0x45) |
| @@ -1420,7 +1423,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
| 1420 | skb_gro_pull(skb, sizeof(*iph)); | 1423 | skb_gro_pull(skb, sizeof(*iph)); |
| 1421 | skb_set_transport_header(skb, skb_gro_offset(skb)); | 1424 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
| 1422 | 1425 | ||
| 1423 | pp = ops->gro_receive(head, skb); | 1426 | pp = ops->callbacks.gro_receive(head, skb); |
| 1424 | 1427 | ||
| 1425 | out_unlock: | 1428 | out_unlock: |
| 1426 | rcu_read_unlock(); | 1429 | rcu_read_unlock(); |
| @@ -1435,7 +1438,7 @@ static int inet_gro_complete(struct sk_buff *skb) | |||
| 1435 | { | 1438 | { |
| 1436 | __be16 newlen = htons(skb->len - skb_network_offset(skb)); | 1439 | __be16 newlen = htons(skb->len - skb_network_offset(skb)); |
| 1437 | struct iphdr *iph = ip_hdr(skb); | 1440 | struct iphdr *iph = ip_hdr(skb); |
| 1438 | const struct net_protocol *ops; | 1441 | const struct net_offload *ops; |
| 1439 | int proto = iph->protocol; | 1442 | int proto = iph->protocol; |
| 1440 | int err = -ENOSYS; | 1443 | int err = -ENOSYS; |
| 1441 | 1444 | ||
| @@ -1443,11 +1446,11 @@ static int inet_gro_complete(struct sk_buff *skb) | |||
| 1443 | iph->tot_len = newlen; | 1446 | iph->tot_len = newlen; |
| 1444 | 1447 | ||
| 1445 | rcu_read_lock(); | 1448 | rcu_read_lock(); |
| 1446 | ops = rcu_dereference(inet_protos[proto]); | 1449 | ops = rcu_dereference(inet_offloads[proto]); |
| 1447 | if (WARN_ON(!ops || !ops->gro_complete)) | 1450 | if (WARN_ON(!ops || !ops->callbacks.gro_complete)) |
| 1448 | goto out_unlock; | 1451 | goto out_unlock; |
| 1449 | 1452 | ||
| 1450 | err = ops->gro_complete(skb); | 1453 | err = ops->callbacks.gro_complete(skb); |
| 1451 | 1454 | ||
| 1452 | out_unlock: | 1455 | out_unlock: |
| 1453 | rcu_read_unlock(); | 1456 | rcu_read_unlock(); |
| @@ -1558,23 +1561,33 @@ static const struct net_protocol tcp_protocol = { | |||
| 1558 | .early_demux = tcp_v4_early_demux, | 1561 | .early_demux = tcp_v4_early_demux, |
| 1559 | .handler = tcp_v4_rcv, | 1562 | .handler = tcp_v4_rcv, |
| 1560 | .err_handler = tcp_v4_err, | 1563 | .err_handler = tcp_v4_err, |
| 1561 | .gso_send_check = tcp_v4_gso_send_check, | ||
| 1562 | .gso_segment = tcp_tso_segment, | ||
| 1563 | .gro_receive = tcp4_gro_receive, | ||
| 1564 | .gro_complete = tcp4_gro_complete, | ||
| 1565 | .no_policy = 1, | 1564 | .no_policy = 1, |
| 1566 | .netns_ok = 1, | 1565 | .netns_ok = 1, |
| 1567 | }; | 1566 | }; |
| 1568 | 1567 | ||
| 1568 | static const struct net_offload tcp_offload = { | ||
| 1569 | .callbacks = { | ||
| 1570 | .gso_send_check = tcp_v4_gso_send_check, | ||
| 1571 | .gso_segment = tcp_tso_segment, | ||
| 1572 | .gro_receive = tcp4_gro_receive, | ||
| 1573 | .gro_complete = tcp4_gro_complete, | ||
| 1574 | }, | ||
| 1575 | }; | ||
| 1576 | |||
| 1569 | static const struct net_protocol udp_protocol = { | 1577 | static const struct net_protocol udp_protocol = { |
| 1570 | .handler = udp_rcv, | 1578 | .handler = udp_rcv, |
| 1571 | .err_handler = udp_err, | 1579 | .err_handler = udp_err, |
| 1572 | .gso_send_check = udp4_ufo_send_check, | ||
| 1573 | .gso_segment = udp4_ufo_fragment, | ||
| 1574 | .no_policy = 1, | 1580 | .no_policy = 1, |
| 1575 | .netns_ok = 1, | 1581 | .netns_ok = 1, |
| 1576 | }; | 1582 | }; |
| 1577 | 1583 | ||
| 1584 | static const struct net_offload udp_offload = { | ||
| 1585 | .callbacks = { | ||
| 1586 | .gso_send_check = udp4_ufo_send_check, | ||
| 1587 | .gso_segment = udp4_ufo_fragment, | ||
| 1588 | }, | ||
| 1589 | }; | ||
| 1590 | |||
| 1578 | static const struct net_protocol icmp_protocol = { | 1591 | static const struct net_protocol icmp_protocol = { |
| 1579 | .handler = icmp_rcv, | 1592 | .handler = icmp_rcv, |
| 1580 | .err_handler = ping_err, | 1593 | .err_handler = ping_err, |
| @@ -1659,13 +1672,35 @@ static int ipv4_proc_init(void); | |||
| 1659 | * IP protocol layer initialiser | 1672 | * IP protocol layer initialiser |
| 1660 | */ | 1673 | */ |
| 1661 | 1674 | ||
| 1675 | static struct packet_offload ip_packet_offload __read_mostly = { | ||
| 1676 | .type = cpu_to_be16(ETH_P_IP), | ||
| 1677 | .callbacks = { | ||
| 1678 | .gso_send_check = inet_gso_send_check, | ||
| 1679 | .gso_segment = inet_gso_segment, | ||
| 1680 | .gro_receive = inet_gro_receive, | ||
| 1681 | .gro_complete = inet_gro_complete, | ||
| 1682 | }, | ||
| 1683 | }; | ||
| 1684 | |||
| 1685 | static int __init ipv4_offload_init(void) | ||
| 1686 | { | ||
| 1687 | /* | ||
| 1688 | * Add offloads | ||
| 1689 | */ | ||
| 1690 | if (inet_add_offload(&udp_offload, IPPROTO_UDP) < 0) | ||
| 1691 | pr_crit("%s: Cannot add UDP protocol offload\n", __func__); | ||
| 1692 | if (inet_add_offload(&tcp_offload, IPPROTO_TCP) < 0) | ||
| 1693 | pr_crit("%s: Cannot add TCP protocol offlaod\n", __func__); | ||
| 1694 | |||
| 1695 | dev_add_offload(&ip_packet_offload); | ||
| 1696 | return 0; | ||
| 1697 | } | ||
| 1698 | |||
| 1699 | fs_initcall(ipv4_offload_init); | ||
| 1700 | |||
| 1662 | static struct packet_type ip_packet_type __read_mostly = { | 1701 | static struct packet_type ip_packet_type __read_mostly = { |
| 1663 | .type = cpu_to_be16(ETH_P_IP), | 1702 | .type = cpu_to_be16(ETH_P_IP), |
| 1664 | .func = ip_rcv, | 1703 | .func = ip_rcv, |
| 1665 | .gso_send_check = inet_gso_send_check, | ||
| 1666 | .gso_segment = inet_gso_segment, | ||
| 1667 | .gro_receive = inet_gro_receive, | ||
| 1668 | .gro_complete = inet_gro_complete, | ||
| 1669 | }; | 1704 | }; |
| 1670 | 1705 | ||
| 1671 | static int __init inet_init(void) | 1706 | static int __init inet_init(void) |
