diff options
Diffstat (limited to 'net')
113 files changed, 3407 insertions, 1352 deletions
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index a91504850195..3c9cf6a8e7fb 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c | |||
@@ -119,7 +119,7 @@ static int vlan_get_tx_queues(struct net *net, | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static int vlan_newlink(struct net_device *dev, | 122 | static int vlan_newlink(struct net *src_net, struct net_device *dev, |
123 | struct nlattr *tb[], struct nlattr *data[]) | 123 | struct nlattr *tb[], struct nlattr *data[]) |
124 | { | 124 | { |
125 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 125 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
@@ -131,7 +131,7 @@ static int vlan_newlink(struct net_device *dev, | |||
131 | 131 | ||
132 | if (!tb[IFLA_LINK]) | 132 | if (!tb[IFLA_LINK]) |
133 | return -EINVAL; | 133 | return -EINVAL; |
134 | real_dev = __dev_get_by_index(dev_net(dev), nla_get_u32(tb[IFLA_LINK])); | 134 | real_dev = __dev_get_by_index(src_net, nla_get_u32(tb[IFLA_LINK])); |
135 | if (!real_dev) | 135 | if (!real_dev) |
136 | return -ENODEV; | 136 | return -ENODEV; |
137 | 137 | ||
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index abe38014b7fd..73ca4d524928 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/if_arp.h> | 56 | #include <linux/if_arp.h> |
57 | #include <linux/smp_lock.h> | 57 | #include <linux/smp_lock.h> |
58 | #include <linux/termios.h> /* For TIOCOUTQ/INQ */ | 58 | #include <linux/termios.h> /* For TIOCOUTQ/INQ */ |
59 | #include <linux/compat.h> | ||
59 | #include <net/datalink.h> | 60 | #include <net/datalink.h> |
60 | #include <net/psnap.h> | 61 | #include <net/psnap.h> |
61 | #include <net/sock.h> | 62 | #include <net/sock.h> |
@@ -922,13 +923,8 @@ static unsigned long atalk_sum_partial(const unsigned char *data, | |||
922 | { | 923 | { |
923 | /* This ought to be unwrapped neatly. I'll trust gcc for now */ | 924 | /* This ought to be unwrapped neatly. I'll trust gcc for now */ |
924 | while (len--) { | 925 | while (len--) { |
925 | sum += *data; | 926 | sum += *data++; |
926 | sum <<= 1; | 927 | sum = rol16(sum, 1); |
927 | if (sum & 0x10000) { | ||
928 | sum++; | ||
929 | sum &= 0xffff; | ||
930 | } | ||
931 | data++; | ||
932 | } | 928 | } |
933 | return sum; | 929 | return sum; |
934 | } | 930 | } |
@@ -1021,7 +1017,8 @@ static struct proto ddp_proto = { | |||
1021 | * Create a socket. Initialise the socket, blank the addresses | 1017 | * Create a socket. Initialise the socket, blank the addresses |
1022 | * set the state. | 1018 | * set the state. |
1023 | */ | 1019 | */ |
1024 | static int atalk_create(struct net *net, struct socket *sock, int protocol) | 1020 | static int atalk_create(struct net *net, struct socket *sock, int protocol, |
1021 | int kern) | ||
1025 | { | 1022 | { |
1026 | struct sock *sk; | 1023 | struct sock *sk; |
1027 | int rc = -ESOCKTNOSUPPORT; | 1024 | int rc = -ESOCKTNOSUPPORT; |
@@ -1054,11 +1051,13 @@ static int atalk_release(struct socket *sock) | |||
1054 | { | 1051 | { |
1055 | struct sock *sk = sock->sk; | 1052 | struct sock *sk = sock->sk; |
1056 | 1053 | ||
1054 | lock_kernel(); | ||
1057 | if (sk) { | 1055 | if (sk) { |
1058 | sock_orphan(sk); | 1056 | sock_orphan(sk); |
1059 | sock->sk = NULL; | 1057 | sock->sk = NULL; |
1060 | atalk_destroy_socket(sk); | 1058 | atalk_destroy_socket(sk); |
1061 | } | 1059 | } |
1060 | unlock_kernel(); | ||
1062 | return 0; | 1061 | return 0; |
1063 | } | 1062 | } |
1064 | 1063 | ||
@@ -1134,6 +1133,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1134 | struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; | 1133 | struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; |
1135 | struct sock *sk = sock->sk; | 1134 | struct sock *sk = sock->sk; |
1136 | struct atalk_sock *at = at_sk(sk); | 1135 | struct atalk_sock *at = at_sk(sk); |
1136 | int err; | ||
1137 | 1137 | ||
1138 | if (!sock_flag(sk, SOCK_ZAPPED) || | 1138 | if (!sock_flag(sk, SOCK_ZAPPED) || |
1139 | addr_len != sizeof(struct sockaddr_at)) | 1139 | addr_len != sizeof(struct sockaddr_at)) |
@@ -1142,37 +1142,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
1142 | if (addr->sat_family != AF_APPLETALK) | 1142 | if (addr->sat_family != AF_APPLETALK) |
1143 | return -EAFNOSUPPORT; | 1143 | return -EAFNOSUPPORT; |
1144 | 1144 | ||
1145 | lock_kernel(); | ||
1145 | if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { | 1146 | if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { |
1146 | struct atalk_addr *ap = atalk_find_primary(); | 1147 | struct atalk_addr *ap = atalk_find_primary(); |
1147 | 1148 | ||
1149 | err = -EADDRNOTAVAIL; | ||
1148 | if (!ap) | 1150 | if (!ap) |
1149 | return -EADDRNOTAVAIL; | 1151 | goto out; |
1150 | 1152 | ||
1151 | at->src_net = addr->sat_addr.s_net = ap->s_net; | 1153 | at->src_net = addr->sat_addr.s_net = ap->s_net; |
1152 | at->src_node = addr->sat_addr.s_node= ap->s_node; | 1154 | at->src_node = addr->sat_addr.s_node= ap->s_node; |
1153 | } else { | 1155 | } else { |
1156 | err = -EADDRNOTAVAIL; | ||
1154 | if (!atalk_find_interface(addr->sat_addr.s_net, | 1157 | if (!atalk_find_interface(addr->sat_addr.s_net, |
1155 | addr->sat_addr.s_node)) | 1158 | addr->sat_addr.s_node)) |
1156 | return -EADDRNOTAVAIL; | 1159 | goto out; |
1157 | 1160 | ||
1158 | at->src_net = addr->sat_addr.s_net; | 1161 | at->src_net = addr->sat_addr.s_net; |
1159 | at->src_node = addr->sat_addr.s_node; | 1162 | at->src_node = addr->sat_addr.s_node; |
1160 | } | 1163 | } |
1161 | 1164 | ||
1162 | if (addr->sat_port == ATADDR_ANYPORT) { | 1165 | if (addr->sat_port == ATADDR_ANYPORT) { |
1163 | int n = atalk_pick_and_bind_port(sk, addr); | 1166 | err = atalk_pick_and_bind_port(sk, addr); |
1164 | 1167 | ||
1165 | if (n < 0) | 1168 | if (err < 0) |
1166 | return n; | 1169 | goto out; |
1167 | } else { | 1170 | } else { |
1168 | at->src_port = addr->sat_port; | 1171 | at->src_port = addr->sat_port; |
1169 | 1172 | ||
1173 | err = -EADDRINUSE; | ||
1170 | if (atalk_find_or_insert_socket(sk, addr)) | 1174 | if (atalk_find_or_insert_socket(sk, addr)) |
1171 | return -EADDRINUSE; | 1175 | goto out; |
1172 | } | 1176 | } |
1173 | 1177 | ||
1174 | sock_reset_flag(sk, SOCK_ZAPPED); | 1178 | sock_reset_flag(sk, SOCK_ZAPPED); |
1175 | return 0; | 1179 | err = 0; |
1180 | out: | ||
1181 | unlock_kernel(); | ||
1182 | return err; | ||
1176 | } | 1183 | } |
1177 | 1184 | ||
1178 | /* Set the address we talk to */ | 1185 | /* Set the address we talk to */ |
@@ -1182,6 +1189,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1182 | struct sock *sk = sock->sk; | 1189 | struct sock *sk = sock->sk; |
1183 | struct atalk_sock *at = at_sk(sk); | 1190 | struct atalk_sock *at = at_sk(sk); |
1184 | struct sockaddr_at *addr; | 1191 | struct sockaddr_at *addr; |
1192 | int err; | ||
1185 | 1193 | ||
1186 | sk->sk_state = TCP_CLOSE; | 1194 | sk->sk_state = TCP_CLOSE; |
1187 | sock->state = SS_UNCONNECTED; | 1195 | sock->state = SS_UNCONNECTED; |
@@ -1206,12 +1214,15 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1206 | #endif | 1214 | #endif |
1207 | } | 1215 | } |
1208 | 1216 | ||
1217 | lock_kernel(); | ||
1218 | err = -EBUSY; | ||
1209 | if (sock_flag(sk, SOCK_ZAPPED)) | 1219 | if (sock_flag(sk, SOCK_ZAPPED)) |
1210 | if (atalk_autobind(sk) < 0) | 1220 | if (atalk_autobind(sk) < 0) |
1211 | return -EBUSY; | 1221 | goto out; |
1212 | 1222 | ||
1223 | err = -ENETUNREACH; | ||
1213 | if (!atrtr_get_dev(&addr->sat_addr)) | 1224 | if (!atrtr_get_dev(&addr->sat_addr)) |
1214 | return -ENETUNREACH; | 1225 | goto out; |
1215 | 1226 | ||
1216 | at->dest_port = addr->sat_port; | 1227 | at->dest_port = addr->sat_port; |
1217 | at->dest_net = addr->sat_addr.s_net; | 1228 | at->dest_net = addr->sat_addr.s_net; |
@@ -1219,7 +1230,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1219 | 1230 | ||
1220 | sock->state = SS_CONNECTED; | 1231 | sock->state = SS_CONNECTED; |
1221 | sk->sk_state = TCP_ESTABLISHED; | 1232 | sk->sk_state = TCP_ESTABLISHED; |
1222 | return 0; | 1233 | err = 0; |
1234 | out: | ||
1235 | unlock_kernel(); | ||
1236 | return err; | ||
1223 | } | 1237 | } |
1224 | 1238 | ||
1225 | /* | 1239 | /* |
@@ -1232,17 +1246,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1232 | struct sockaddr_at sat; | 1246 | struct sockaddr_at sat; |
1233 | struct sock *sk = sock->sk; | 1247 | struct sock *sk = sock->sk; |
1234 | struct atalk_sock *at = at_sk(sk); | 1248 | struct atalk_sock *at = at_sk(sk); |
1249 | int err; | ||
1235 | 1250 | ||
1251 | lock_kernel(); | ||
1252 | err = -ENOBUFS; | ||
1236 | if (sock_flag(sk, SOCK_ZAPPED)) | 1253 | if (sock_flag(sk, SOCK_ZAPPED)) |
1237 | if (atalk_autobind(sk) < 0) | 1254 | if (atalk_autobind(sk) < 0) |
1238 | return -ENOBUFS; | 1255 | goto out; |
1239 | 1256 | ||
1240 | *uaddr_len = sizeof(struct sockaddr_at); | 1257 | *uaddr_len = sizeof(struct sockaddr_at); |
1241 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); | 1258 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); |
1242 | 1259 | ||
1243 | if (peer) { | 1260 | if (peer) { |
1261 | err = -ENOTCONN; | ||
1244 | if (sk->sk_state != TCP_ESTABLISHED) | 1262 | if (sk->sk_state != TCP_ESTABLISHED) |
1245 | return -ENOTCONN; | 1263 | goto out; |
1246 | 1264 | ||
1247 | sat.sat_addr.s_net = at->dest_net; | 1265 | sat.sat_addr.s_net = at->dest_net; |
1248 | sat.sat_addr.s_node = at->dest_node; | 1266 | sat.sat_addr.s_node = at->dest_node; |
@@ -1253,9 +1271,23 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1253 | sat.sat_port = at->src_port; | 1271 | sat.sat_port = at->src_port; |
1254 | } | 1272 | } |
1255 | 1273 | ||
1274 | err = 0; | ||
1256 | sat.sat_family = AF_APPLETALK; | 1275 | sat.sat_family = AF_APPLETALK; |
1257 | memcpy(uaddr, &sat, sizeof(sat)); | 1276 | memcpy(uaddr, &sat, sizeof(sat)); |
1258 | return 0; | 1277 | |
1278 | out: | ||
1279 | unlock_kernel(); | ||
1280 | return err; | ||
1281 | } | ||
1282 | |||
1283 | static unsigned int atalk_poll(struct file *file, struct socket *sock, | ||
1284 | poll_table *wait) | ||
1285 | { | ||
1286 | int err; | ||
1287 | lock_kernel(); | ||
1288 | err = datagram_poll(file, sock, wait); | ||
1289 | unlock_kernel(); | ||
1290 | return err; | ||
1259 | } | 1291 | } |
1260 | 1292 | ||
1261 | #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) | 1293 | #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) |
@@ -1563,23 +1595,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1563 | if (len > DDP_MAXSZ) | 1595 | if (len > DDP_MAXSZ) |
1564 | return -EMSGSIZE; | 1596 | return -EMSGSIZE; |
1565 | 1597 | ||
1598 | lock_kernel(); | ||
1566 | if (usat) { | 1599 | if (usat) { |
1600 | err = -EBUSY; | ||
1567 | if (sock_flag(sk, SOCK_ZAPPED)) | 1601 | if (sock_flag(sk, SOCK_ZAPPED)) |
1568 | if (atalk_autobind(sk) < 0) | 1602 | if (atalk_autobind(sk) < 0) |
1569 | return -EBUSY; | 1603 | goto out; |
1570 | 1604 | ||
1605 | err = -EINVAL; | ||
1571 | if (msg->msg_namelen < sizeof(*usat) || | 1606 | if (msg->msg_namelen < sizeof(*usat) || |
1572 | usat->sat_family != AF_APPLETALK) | 1607 | usat->sat_family != AF_APPLETALK) |
1573 | return -EINVAL; | 1608 | goto out; |
1574 | 1609 | ||
1610 | err = -EPERM; | ||
1575 | /* netatalk didn't implement this check */ | 1611 | /* netatalk didn't implement this check */ |
1576 | if (usat->sat_addr.s_node == ATADDR_BCAST && | 1612 | if (usat->sat_addr.s_node == ATADDR_BCAST && |
1577 | !sock_flag(sk, SOCK_BROADCAST)) { | 1613 | !sock_flag(sk, SOCK_BROADCAST)) { |
1578 | return -EPERM; | 1614 | goto out; |
1579 | } | 1615 | } |
1580 | } else { | 1616 | } else { |
1617 | err = -ENOTCONN; | ||
1581 | if (sk->sk_state != TCP_ESTABLISHED) | 1618 | if (sk->sk_state != TCP_ESTABLISHED) |
1582 | return -ENOTCONN; | 1619 | goto out; |
1583 | usat = &local_satalk; | 1620 | usat = &local_satalk; |
1584 | usat->sat_family = AF_APPLETALK; | 1621 | usat->sat_family = AF_APPLETALK; |
1585 | usat->sat_port = at->dest_port; | 1622 | usat->sat_port = at->dest_port; |
@@ -1603,8 +1640,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1603 | 1640 | ||
1604 | rt = atrtr_find(&at_hint); | 1641 | rt = atrtr_find(&at_hint); |
1605 | } | 1642 | } |
1643 | err = ENETUNREACH; | ||
1606 | if (!rt) | 1644 | if (!rt) |
1607 | return -ENETUNREACH; | 1645 | goto out; |
1608 | 1646 | ||
1609 | dev = rt->dev; | 1647 | dev = rt->dev; |
1610 | 1648 | ||
@@ -1614,7 +1652,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1614 | size += dev->hard_header_len; | 1652 | size += dev->hard_header_len; |
1615 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); | 1653 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); |
1616 | if (!skb) | 1654 | if (!skb) |
1617 | return err; | 1655 | goto out; |
1618 | 1656 | ||
1619 | skb->sk = sk; | 1657 | skb->sk = sk; |
1620 | skb_reserve(skb, ddp_dl->header_length); | 1658 | skb_reserve(skb, ddp_dl->header_length); |
@@ -1637,7 +1675,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1637 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | 1675 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); |
1638 | if (err) { | 1676 | if (err) { |
1639 | kfree_skb(skb); | 1677 | kfree_skb(skb); |
1640 | return -EFAULT; | 1678 | err = -EFAULT; |
1679 | goto out; | ||
1641 | } | 1680 | } |
1642 | 1681 | ||
1643 | if (sk->sk_no_check == 1) | 1682 | if (sk->sk_no_check == 1) |
@@ -1676,7 +1715,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1676 | rt = atrtr_find(&at_lo); | 1715 | rt = atrtr_find(&at_lo); |
1677 | if (!rt) { | 1716 | if (!rt) { |
1678 | kfree_skb(skb); | 1717 | kfree_skb(skb); |
1679 | return -ENETUNREACH; | 1718 | err = -ENETUNREACH; |
1719 | goto out; | ||
1680 | } | 1720 | } |
1681 | dev = rt->dev; | 1721 | dev = rt->dev; |
1682 | skb->dev = dev; | 1722 | skb->dev = dev; |
@@ -1696,7 +1736,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1696 | } | 1736 | } |
1697 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); | 1737 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); |
1698 | 1738 | ||
1699 | return len; | 1739 | out: |
1740 | unlock_kernel(); | ||
1741 | return err ? : len; | ||
1700 | } | 1742 | } |
1701 | 1743 | ||
1702 | static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | 1744 | static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, |
@@ -1708,10 +1750,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1708 | int copied = 0; | 1750 | int copied = 0; |
1709 | int offset = 0; | 1751 | int offset = 0; |
1710 | int err = 0; | 1752 | int err = 0; |
1711 | struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1753 | struct sk_buff *skb; |
1754 | |||
1755 | lock_kernel(); | ||
1756 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | ||
1712 | flags & MSG_DONTWAIT, &err); | 1757 | flags & MSG_DONTWAIT, &err); |
1713 | if (!skb) | 1758 | if (!skb) |
1714 | return err; | 1759 | goto out; |
1715 | 1760 | ||
1716 | /* FIXME: use skb->cb to be able to use shared skbs */ | 1761 | /* FIXME: use skb->cb to be able to use shared skbs */ |
1717 | ddp = ddp_hdr(skb); | 1762 | ddp = ddp_hdr(skb); |
@@ -1739,6 +1784,9 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr | |||
1739 | } | 1784 | } |
1740 | 1785 | ||
1741 | skb_free_datagram(sk, skb); /* Free the datagram. */ | 1786 | skb_free_datagram(sk, skb); /* Free the datagram. */ |
1787 | |||
1788 | out: | ||
1789 | unlock_kernel(); | ||
1742 | return err ? : copied; | 1790 | return err ? : copied; |
1743 | } | 1791 | } |
1744 | 1792 | ||
@@ -1810,12 +1858,14 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1810 | static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 1858 | static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
1811 | { | 1859 | { |
1812 | /* | 1860 | /* |
1813 | * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And | 1861 | * SIOCATALKDIFADDR is a SIOCPROTOPRIVATE ioctl number, so we |
1814 | * SIOCATALKDIFADDR is handled by upper layer as well, so there is | 1862 | * cannot handle it in common code. The data we access if ifreq |
1815 | * nothing to do. Eventually SIOCATALKDIFADDR should be moved | 1863 | * here is compatible, so we can simply call the native |
1816 | * here so there is no generic SIOCPROTOPRIVATE translation in the | 1864 | * handler. |
1817 | * system. | ||
1818 | */ | 1865 | */ |
1866 | if (cmd == SIOCATALKDIFADDR) | ||
1867 | return atalk_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); | ||
1868 | |||
1819 | return -ENOIOCTLCMD; | 1869 | return -ENOIOCTLCMD; |
1820 | } | 1870 | } |
1821 | #endif | 1871 | #endif |
@@ -1827,7 +1877,7 @@ static const struct net_proto_family atalk_family_ops = { | |||
1827 | .owner = THIS_MODULE, | 1877 | .owner = THIS_MODULE, |
1828 | }; | 1878 | }; |
1829 | 1879 | ||
1830 | static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | 1880 | static const struct proto_ops atalk_dgram_ops = { |
1831 | .family = PF_APPLETALK, | 1881 | .family = PF_APPLETALK, |
1832 | .owner = THIS_MODULE, | 1882 | .owner = THIS_MODULE, |
1833 | .release = atalk_release, | 1883 | .release = atalk_release, |
@@ -1836,7 +1886,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | |||
1836 | .socketpair = sock_no_socketpair, | 1886 | .socketpair = sock_no_socketpair, |
1837 | .accept = sock_no_accept, | 1887 | .accept = sock_no_accept, |
1838 | .getname = atalk_getname, | 1888 | .getname = atalk_getname, |
1839 | .poll = datagram_poll, | 1889 | .poll = atalk_poll, |
1840 | .ioctl = atalk_ioctl, | 1890 | .ioctl = atalk_ioctl, |
1841 | #ifdef CONFIG_COMPAT | 1891 | #ifdef CONFIG_COMPAT |
1842 | .compat_ioctl = atalk_compat_ioctl, | 1892 | .compat_ioctl = atalk_compat_ioctl, |
@@ -1851,8 +1901,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { | |||
1851 | .sendpage = sock_no_sendpage, | 1901 | .sendpage = sock_no_sendpage, |
1852 | }; | 1902 | }; |
1853 | 1903 | ||
1854 | SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK); | ||
1855 | |||
1856 | static struct notifier_block ddp_notifier = { | 1904 | static struct notifier_block ddp_notifier = { |
1857 | .notifier_call = ddp_device_event, | 1905 | .notifier_call = ddp_device_event, |
1858 | }; | 1906 | }; |
diff --git a/net/atm/pvc.c b/net/atm/pvc.c index a6e1fdbae87f..8d74e62b0d79 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c | |||
@@ -127,7 +127,8 @@ static const struct proto_ops pvc_proto_ops = { | |||
127 | }; | 127 | }; |
128 | 128 | ||
129 | 129 | ||
130 | static int pvc_create(struct net *net, struct socket *sock,int protocol) | 130 | static int pvc_create(struct net *net, struct socket *sock, int protocol, |
131 | int kern) | ||
131 | { | 132 | { |
132 | if (net != &init_net) | 133 | if (net != &init_net) |
133 | return -EAFNOSUPPORT; | 134 | return -EAFNOSUPPORT; |
diff --git a/net/atm/svc.c b/net/atm/svc.c index 819354233318..c7395070ee78 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include "signaling.h" | 25 | #include "signaling.h" |
26 | #include "addr.h" | 26 | #include "addr.h" |
27 | 27 | ||
28 | static int svc_create(struct net *net, struct socket *sock,int protocol); | 28 | static int svc_create(struct net *net, struct socket *sock, int protocol, int kern); |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * Note: since all this is still nicely synchronized with the signaling demon, | 31 | * Note: since all this is still nicely synchronized with the signaling demon, |
@@ -330,7 +330,7 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags) | |||
330 | 330 | ||
331 | lock_sock(sk); | 331 | lock_sock(sk); |
332 | 332 | ||
333 | error = svc_create(sock_net(sk), newsock,0); | 333 | error = svc_create(sock_net(sk), newsock, 0, 0); |
334 | if (error) | 334 | if (error) |
335 | goto out; | 335 | goto out; |
336 | 336 | ||
@@ -650,7 +650,8 @@ static const struct proto_ops svc_proto_ops = { | |||
650 | }; | 650 | }; |
651 | 651 | ||
652 | 652 | ||
653 | static int svc_create(struct net *net, struct socket *sock,int protocol) | 653 | static int svc_create(struct net *net, struct socket *sock, int protocol, |
654 | int kern) | ||
654 | { | 655 | { |
655 | int error; | 656 | int error; |
656 | 657 | ||
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index f1e998b2796e..d6ddfa4c4471 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -799,7 +799,8 @@ static struct proto ax25_proto = { | |||
799 | .obj_size = sizeof(struct sock), | 799 | .obj_size = sizeof(struct sock), |
800 | }; | 800 | }; |
801 | 801 | ||
802 | static int ax25_create(struct net *net, struct socket *sock, int protocol) | 802 | static int ax25_create(struct net *net, struct socket *sock, int protocol, |
803 | int kern) | ||
803 | { | 804 | { |
804 | struct sock *sk; | 805 | struct sock *sk; |
805 | ax25_cb *ax25; | 806 | ax25_cb *ax25; |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 399e59c9c6cb..087cc51f5927 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -126,7 +126,8 @@ int bt_sock_unregister(int proto) | |||
126 | } | 126 | } |
127 | EXPORT_SYMBOL(bt_sock_unregister); | 127 | EXPORT_SYMBOL(bt_sock_unregister); |
128 | 128 | ||
129 | static int bt_sock_create(struct net *net, struct socket *sock, int proto) | 129 | static int bt_sock_create(struct net *net, struct socket *sock, int proto, |
130 | int kern) | ||
130 | { | 131 | { |
131 | int err; | 132 | int err; |
132 | 133 | ||
@@ -144,7 +145,7 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto) | |||
144 | read_lock(&bt_proto_lock); | 145 | read_lock(&bt_proto_lock); |
145 | 146 | ||
146 | if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { | 147 | if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { |
147 | err = bt_proto[proto]->create(net, sock, proto); | 148 | err = bt_proto[proto]->create(net, sock, proto, kern); |
148 | bt_sock_reclassify_lock(sock, proto); | 149 | bt_sock_reclassify_lock(sock, proto); |
149 | module_put(bt_proto[proto]->owner); | 150 | module_put(bt_proto[proto]->owner); |
150 | } | 151 | } |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 0a2c5460bb48..2ff6ac7b2ed4 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -195,7 +195,8 @@ static struct proto bnep_proto = { | |||
195 | .obj_size = sizeof(struct bt_sock) | 195 | .obj_size = sizeof(struct bt_sock) |
196 | }; | 196 | }; |
197 | 197 | ||
198 | static int bnep_sock_create(struct net *net, struct socket *sock, int protocol) | 198 | static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, |
199 | int kern) | ||
199 | { | 200 | { |
200 | struct sock *sk; | 201 | struct sock *sk; |
201 | 202 | ||
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index de7c8040bc56..978cc3a718ad 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -190,7 +190,8 @@ static struct proto cmtp_proto = { | |||
190 | .obj_size = sizeof(struct bt_sock) | 190 | .obj_size = sizeof(struct bt_sock) |
191 | }; | 191 | }; |
192 | 192 | ||
193 | static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol) | 193 | static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, |
194 | int kern) | ||
194 | { | 195 | { |
195 | struct sock *sk; | 196 | struct sock *sk; |
196 | 197 | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index e7395f231989..1ca5c7ca9bd4 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -621,7 +621,8 @@ static struct proto hci_sk_proto = { | |||
621 | .obj_size = sizeof(struct hci_pinfo) | 621 | .obj_size = sizeof(struct hci_pinfo) |
622 | }; | 622 | }; |
623 | 623 | ||
624 | static int hci_sock_create(struct net *net, struct socket *sock, int protocol) | 624 | static int hci_sock_create(struct net *net, struct socket *sock, int protocol, |
625 | int kern) | ||
625 | { | 626 | { |
626 | struct sock *sk; | 627 | struct sock *sk; |
627 | 628 | ||
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 4beb6a7a2953..9cfef68b9fec 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -241,7 +241,8 @@ static struct proto hidp_proto = { | |||
241 | .obj_size = sizeof(struct bt_sock) | 241 | .obj_size = sizeof(struct bt_sock) |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static int hidp_sock_create(struct net *net, struct socket *sock, int protocol) | 244 | static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, |
245 | int kern) | ||
245 | { | 246 | { |
246 | struct sock *sk; | 247 | struct sock *sk; |
247 | 248 | ||
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index d65101d92ee5..ff0233df6246 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -819,7 +819,8 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
819 | return sk; | 819 | return sk; |
820 | } | 820 | } |
821 | 821 | ||
822 | static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol) | 822 | static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, |
823 | int kern) | ||
823 | { | 824 | { |
824 | struct sock *sk; | 825 | struct sock *sk; |
825 | 826 | ||
@@ -831,7 +832,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol) | |||
831 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | 832 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) |
832 | return -ESOCKTNOSUPPORT; | 833 | return -ESOCKTNOSUPPORT; |
833 | 834 | ||
834 | if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW)) | 835 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
835 | return -EPERM; | 836 | return -EPERM; |
836 | 837 | ||
837 | sock->ops = &l2cap_sock_ops; | 838 | sock->ops = &l2cap_sock_ops; |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index d3bfc1b0afb1..4b5968dda673 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -323,7 +323,8 @@ static struct sock *rfcomm_sock_alloc(struct net *net, struct socket *sock, int | |||
323 | return sk; | 323 | return sk; |
324 | } | 324 | } |
325 | 325 | ||
326 | static int rfcomm_sock_create(struct net *net, struct socket *sock, int protocol) | 326 | static int rfcomm_sock_create(struct net *net, struct socket *sock, |
327 | int protocol, int kern) | ||
327 | { | 328 | { |
328 | struct sock *sk; | 329 | struct sock *sk; |
329 | 330 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 694a65541b73..dd8f6ec57dce 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -430,7 +430,8 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock, int pro | |||
430 | return sk; | 430 | return sk; |
431 | } | 431 | } |
432 | 432 | ||
433 | static int sco_sock_create(struct net *net, struct socket *sock, int protocol) | 433 | static int sco_sock_create(struct net *net, struct socket *sock, int protocol, |
434 | int kern) | ||
434 | { | 435 | { |
435 | struct sock *sk; | 436 | struct sock *sk; |
436 | 437 | ||
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 2117e5ba24c8..a6f74b2b9571 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -377,12 +377,16 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
377 | struct net_bridge_port *p; | 377 | struct net_bridge_port *p; |
378 | int err = 0; | 378 | int err = 0; |
379 | 379 | ||
380 | if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER) | 380 | /* Don't allow bridging non-ethernet like devices */ |
381 | if ((dev->flags & IFF_LOOPBACK) || | ||
382 | dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) | ||
381 | return -EINVAL; | 383 | return -EINVAL; |
382 | 384 | ||
385 | /* No bridging of bridges */ | ||
383 | if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) | 386 | if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) |
384 | return -ELOOP; | 387 | return -ELOOP; |
385 | 388 | ||
389 | /* Device is already being bridged */ | ||
386 | if (dev->br_port != NULL) | 390 | if (dev->br_port != NULL) |
387 | return -EBUSY; | 391 | return -EBUSY; |
388 | 392 | ||
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 6a6433daaf27..2af6e4a90262 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -81,6 +81,7 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf, | |||
81 | return num; | 81 | return num; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* called with RTNL */ | ||
84 | static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | 85 | static int add_del_if(struct net_bridge *br, int ifindex, int isadd) |
85 | { | 86 | { |
86 | struct net_device *dev; | 87 | struct net_device *dev; |
@@ -89,7 +90,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | |||
89 | if (!capable(CAP_NET_ADMIN)) | 90 | if (!capable(CAP_NET_ADMIN)) |
90 | return -EPERM; | 91 | return -EPERM; |
91 | 92 | ||
92 | dev = dev_get_by_index(dev_net(br->dev), ifindex); | 93 | dev = __dev_get_by_index(dev_net(br->dev), ifindex); |
93 | if (dev == NULL) | 94 | if (dev == NULL) |
94 | return -EINVAL; | 95 | return -EINVAL; |
95 | 96 | ||
@@ -98,7 +99,6 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | |||
98 | else | 99 | else |
99 | ret = br_del_if(br, dev); | 100 | ret = br_del_if(br, dev); |
100 | 101 | ||
101 | dev_put(dev); | ||
102 | return ret; | 102 | return ret; |
103 | } | 103 | } |
104 | 104 | ||
diff --git a/net/can/af_can.c b/net/can/af_can.c index 3f2eb27e1ffb..833bd838edc6 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -114,7 +114,8 @@ static void can_sock_destruct(struct sock *sk) | |||
114 | skb_queue_purge(&sk->sk_receive_queue); | 114 | skb_queue_purge(&sk->sk_receive_queue); |
115 | } | 115 | } |
116 | 116 | ||
117 | static int can_create(struct net *net, struct socket *sock, int protocol) | 117 | static int can_create(struct net *net, struct socket *sock, int protocol, |
118 | int kern) | ||
118 | { | 119 | { |
119 | struct sock *sk; | 120 | struct sock *sk; |
120 | struct can_proto *cp; | 121 | struct can_proto *cp; |
@@ -160,11 +161,6 @@ static int can_create(struct net *net, struct socket *sock, int protocol) | |||
160 | goto errout; | 161 | goto errout; |
161 | } | 162 | } |
162 | 163 | ||
163 | if (cp->capability >= 0 && !capable(cp->capability)) { | ||
164 | err = -EPERM; | ||
165 | goto errout; | ||
166 | } | ||
167 | |||
168 | sock->ops = cp->ops; | 164 | sock->ops = cp->ops; |
169 | 165 | ||
170 | sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot); | 166 | sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot); |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 2f47039c79dd..c302c2ec959c 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -132,23 +132,27 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk) | |||
132 | /* | 132 | /* |
133 | * procfs functions | 133 | * procfs functions |
134 | */ | 134 | */ |
135 | static char *bcm_proc_getifname(int ifindex) | 135 | static char *bcm_proc_getifname(char *result, int ifindex) |
136 | { | 136 | { |
137 | struct net_device *dev; | 137 | struct net_device *dev; |
138 | 138 | ||
139 | if (!ifindex) | 139 | if (!ifindex) |
140 | return "any"; | 140 | return "any"; |
141 | 141 | ||
142 | /* no usage counting */ | 142 | read_lock(&dev_base_lock); |
143 | dev = __dev_get_by_index(&init_net, ifindex); | 143 | dev = __dev_get_by_index(&init_net, ifindex); |
144 | if (dev) | 144 | if (dev) |
145 | return dev->name; | 145 | strcpy(result, dev->name); |
146 | else | ||
147 | strcpy(result, "???"); | ||
148 | read_unlock(&dev_base_lock); | ||
146 | 149 | ||
147 | return "???"; | 150 | return result; |
148 | } | 151 | } |
149 | 152 | ||
150 | static int bcm_proc_show(struct seq_file *m, void *v) | 153 | static int bcm_proc_show(struct seq_file *m, void *v) |
151 | { | 154 | { |
155 | char ifname[IFNAMSIZ]; | ||
152 | struct sock *sk = (struct sock *)m->private; | 156 | struct sock *sk = (struct sock *)m->private; |
153 | struct bcm_sock *bo = bcm_sk(sk); | 157 | struct bcm_sock *bo = bcm_sk(sk); |
154 | struct bcm_op *op; | 158 | struct bcm_op *op; |
@@ -157,7 +161,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
157 | seq_printf(m, " / sk %p", sk); | 161 | seq_printf(m, " / sk %p", sk); |
158 | seq_printf(m, " / bo %p", bo); | 162 | seq_printf(m, " / bo %p", bo); |
159 | seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); | 163 | seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs); |
160 | seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex)); | 164 | seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex)); |
161 | seq_printf(m, " <<<\n"); | 165 | seq_printf(m, " <<<\n"); |
162 | 166 | ||
163 | list_for_each_entry(op, &bo->rx_ops, list) { | 167 | list_for_each_entry(op, &bo->rx_ops, list) { |
@@ -169,7 +173,7 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
169 | continue; | 173 | continue; |
170 | 174 | ||
171 | seq_printf(m, "rx_op: %03X %-5s ", | 175 | seq_printf(m, "rx_op: %03X %-5s ", |
172 | op->can_id, bcm_proc_getifname(op->ifindex)); | 176 | op->can_id, bcm_proc_getifname(ifname, op->ifindex)); |
173 | seq_printf(m, "[%d]%c ", op->nframes, | 177 | seq_printf(m, "[%d]%c ", op->nframes, |
174 | (op->flags & RX_CHECK_DLC)?'d':' '); | 178 | (op->flags & RX_CHECK_DLC)?'d':' '); |
175 | if (op->kt_ival1.tv64) | 179 | if (op->kt_ival1.tv64) |
@@ -194,7 +198,8 @@ static int bcm_proc_show(struct seq_file *m, void *v) | |||
194 | list_for_each_entry(op, &bo->tx_ops, list) { | 198 | list_for_each_entry(op, &bo->tx_ops, list) { |
195 | 199 | ||
196 | seq_printf(m, "tx_op: %03X %s [%d] ", | 200 | seq_printf(m, "tx_op: %03X %s [%d] ", |
197 | op->can_id, bcm_proc_getifname(op->ifindex), | 201 | op->can_id, |
202 | bcm_proc_getifname(ifname, op->ifindex), | ||
198 | op->nframes); | 203 | op->nframes); |
199 | 204 | ||
200 | if (op->kt_ival1.tv64) | 205 | if (op->kt_ival1.tv64) |
@@ -1576,7 +1581,6 @@ static struct proto bcm_proto __read_mostly = { | |||
1576 | static struct can_proto bcm_can_proto __read_mostly = { | 1581 | static struct can_proto bcm_can_proto __read_mostly = { |
1577 | .type = SOCK_DGRAM, | 1582 | .type = SOCK_DGRAM, |
1578 | .protocol = CAN_BCM, | 1583 | .protocol = CAN_BCM, |
1579 | .capability = -1, | ||
1580 | .ops = &bcm_ops, | 1584 | .ops = &bcm_ops, |
1581 | .prot = &bcm_proto, | 1585 | .prot = &bcm_proto, |
1582 | }; | 1586 | }; |
diff --git a/net/can/raw.c b/net/can/raw.c index 6e77db58b9e6..abca920440b5 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -742,7 +742,6 @@ static struct proto raw_proto __read_mostly = { | |||
742 | static struct can_proto raw_can_proto __read_mostly = { | 742 | static struct can_proto raw_can_proto __read_mostly = { |
743 | .type = SOCK_RAW, | 743 | .type = SOCK_RAW, |
744 | .protocol = CAN_RAW, | 744 | .protocol = CAN_RAW, |
745 | .capability = -1, | ||
746 | .ops = &raw_ops, | 745 | .ops = &raw_ops, |
747 | .prot = &raw_proto, | 746 | .prot = &raw_proto, |
748 | }; | 747 | }; |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 4d57f5e12b05..95c2e0840d0d 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -224,6 +224,15 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) | |||
224 | consume_skb(skb); | 224 | consume_skb(skb); |
225 | sk_mem_reclaim_partial(sk); | 225 | sk_mem_reclaim_partial(sk); |
226 | } | 226 | } |
227 | EXPORT_SYMBOL(skb_free_datagram); | ||
228 | |||
229 | void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb) | ||
230 | { | ||
231 | lock_sock(sk); | ||
232 | skb_free_datagram(sk, skb); | ||
233 | release_sock(sk); | ||
234 | } | ||
235 | EXPORT_SYMBOL(skb_free_datagram_locked); | ||
227 | 236 | ||
228 | /** | 237 | /** |
229 | * skb_kill_datagram - Free a datagram skbuff forcibly | 238 | * skb_kill_datagram - Free a datagram skbuff forcibly |
@@ -753,5 +762,4 @@ unsigned int datagram_poll(struct file *file, struct socket *sock, | |||
753 | EXPORT_SYMBOL(datagram_poll); | 762 | EXPORT_SYMBOL(datagram_poll); |
754 | EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); | 763 | EXPORT_SYMBOL(skb_copy_and_csum_datagram_iovec); |
755 | EXPORT_SYMBOL(skb_copy_datagram_iovec); | 764 | EXPORT_SYMBOL(skb_copy_datagram_iovec); |
756 | EXPORT_SYMBOL(skb_free_datagram); | ||
757 | EXPORT_SYMBOL(skb_recv_datagram); | 765 | EXPORT_SYMBOL(skb_recv_datagram); |
diff --git a/net/core/dev.c b/net/core/dev.c index 631cc40da197..bf629ac08b87 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -175,7 +175,7 @@ static struct list_head ptype_all __read_mostly; /* Taps */ | |||
175 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl | 175 | * The @dev_base_head list is protected by @dev_base_lock and the rtnl |
176 | * semaphore. | 176 | * semaphore. |
177 | * | 177 | * |
178 | * Pure readers hold dev_base_lock for reading. | 178 | * Pure readers hold dev_base_lock for reading, or rcu_read_lock() |
179 | * | 179 | * |
180 | * Writers must hold the rtnl semaphore while they loop through the | 180 | * Writers must hold the rtnl semaphore while they loop through the |
181 | * dev_base_head list, and hold dev_base_lock for writing when they do the | 181 | * dev_base_head list, and hold dev_base_lock for writing when they do the |
@@ -212,8 +212,8 @@ static int list_netdevice(struct net_device *dev) | |||
212 | ASSERT_RTNL(); | 212 | ASSERT_RTNL(); |
213 | 213 | ||
214 | write_lock_bh(&dev_base_lock); | 214 | write_lock_bh(&dev_base_lock); |
215 | list_add_tail(&dev->dev_list, &net->dev_base_head); | 215 | list_add_tail_rcu(&dev->dev_list, &net->dev_base_head); |
216 | hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name)); | 216 | hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); |
217 | hlist_add_head_rcu(&dev->index_hlist, | 217 | hlist_add_head_rcu(&dev->index_hlist, |
218 | dev_index_hash(net, dev->ifindex)); | 218 | dev_index_hash(net, dev->ifindex)); |
219 | write_unlock_bh(&dev_base_lock); | 219 | write_unlock_bh(&dev_base_lock); |
@@ -229,8 +229,8 @@ static void unlist_netdevice(struct net_device *dev) | |||
229 | 229 | ||
230 | /* Unlink dev from the device chain */ | 230 | /* Unlink dev from the device chain */ |
231 | write_lock_bh(&dev_base_lock); | 231 | write_lock_bh(&dev_base_lock); |
232 | list_del(&dev->dev_list); | 232 | list_del_rcu(&dev->dev_list); |
233 | hlist_del(&dev->name_hlist); | 233 | hlist_del_rcu(&dev->name_hlist); |
234 | hlist_del_rcu(&dev->index_hlist); | 234 | hlist_del_rcu(&dev->index_hlist); |
235 | write_unlock_bh(&dev_base_lock); | 235 | write_unlock_bh(&dev_base_lock); |
236 | } | 236 | } |
@@ -587,18 +587,44 @@ __setup("netdev=", netdev_boot_setup); | |||
587 | struct net_device *__dev_get_by_name(struct net *net, const char *name) | 587 | struct net_device *__dev_get_by_name(struct net *net, const char *name) |
588 | { | 588 | { |
589 | struct hlist_node *p; | 589 | struct hlist_node *p; |
590 | struct net_device *dev; | ||
591 | struct hlist_head *head = dev_name_hash(net, name); | ||
590 | 592 | ||
591 | hlist_for_each(p, dev_name_hash(net, name)) { | 593 | hlist_for_each_entry(dev, p, head, name_hlist) |
592 | struct net_device *dev | ||
593 | = hlist_entry(p, struct net_device, name_hlist); | ||
594 | if (!strncmp(dev->name, name, IFNAMSIZ)) | 594 | if (!strncmp(dev->name, name, IFNAMSIZ)) |
595 | return dev; | 595 | return dev; |
596 | } | 596 | |
597 | return NULL; | 597 | return NULL; |
598 | } | 598 | } |
599 | EXPORT_SYMBOL(__dev_get_by_name); | 599 | EXPORT_SYMBOL(__dev_get_by_name); |
600 | 600 | ||
601 | /** | 601 | /** |
602 | * dev_get_by_name_rcu - find a device by its name | ||
603 | * @net: the applicable net namespace | ||
604 | * @name: name to find | ||
605 | * | ||
606 | * Find an interface by name. | ||
607 | * If the name is found a pointer to the device is returned. | ||
608 | * If the name is not found then %NULL is returned. | ||
609 | * The reference counters are not incremented so the caller must be | ||
610 | * careful with locks. The caller must hold RCU lock. | ||
611 | */ | ||
612 | |||
613 | struct net_device *dev_get_by_name_rcu(struct net *net, const char *name) | ||
614 | { | ||
615 | struct hlist_node *p; | ||
616 | struct net_device *dev; | ||
617 | struct hlist_head *head = dev_name_hash(net, name); | ||
618 | |||
619 | hlist_for_each_entry_rcu(dev, p, head, name_hlist) | ||
620 | if (!strncmp(dev->name, name, IFNAMSIZ)) | ||
621 | return dev; | ||
622 | |||
623 | return NULL; | ||
624 | } | ||
625 | EXPORT_SYMBOL(dev_get_by_name_rcu); | ||
626 | |||
627 | /** | ||
602 | * dev_get_by_name - find a device by its name | 628 | * dev_get_by_name - find a device by its name |
603 | * @net: the applicable net namespace | 629 | * @net: the applicable net namespace |
604 | * @name: name to find | 630 | * @name: name to find |
@@ -614,11 +640,11 @@ struct net_device *dev_get_by_name(struct net *net, const char *name) | |||
614 | { | 640 | { |
615 | struct net_device *dev; | 641 | struct net_device *dev; |
616 | 642 | ||
617 | read_lock(&dev_base_lock); | 643 | rcu_read_lock(); |
618 | dev = __dev_get_by_name(net, name); | 644 | dev = dev_get_by_name_rcu(net, name); |
619 | if (dev) | 645 | if (dev) |
620 | dev_hold(dev); | 646 | dev_hold(dev); |
621 | read_unlock(&dev_base_lock); | 647 | rcu_read_unlock(); |
622 | return dev; | 648 | return dev; |
623 | } | 649 | } |
624 | EXPORT_SYMBOL(dev_get_by_name); | 650 | EXPORT_SYMBOL(dev_get_by_name); |
@@ -638,13 +664,13 @@ EXPORT_SYMBOL(dev_get_by_name); | |||
638 | struct net_device *__dev_get_by_index(struct net *net, int ifindex) | 664 | struct net_device *__dev_get_by_index(struct net *net, int ifindex) |
639 | { | 665 | { |
640 | struct hlist_node *p; | 666 | struct hlist_node *p; |
667 | struct net_device *dev; | ||
668 | struct hlist_head *head = dev_index_hash(net, ifindex); | ||
641 | 669 | ||
642 | hlist_for_each(p, dev_index_hash(net, ifindex)) { | 670 | hlist_for_each_entry(dev, p, head, index_hlist) |
643 | struct net_device *dev | ||
644 | = hlist_entry(p, struct net_device, index_hlist); | ||
645 | if (dev->ifindex == ifindex) | 671 | if (dev->ifindex == ifindex) |
646 | return dev; | 672 | return dev; |
647 | } | 673 | |
648 | return NULL; | 674 | return NULL; |
649 | } | 675 | } |
650 | EXPORT_SYMBOL(__dev_get_by_index); | 676 | EXPORT_SYMBOL(__dev_get_by_index); |
@@ -773,15 +799,15 @@ struct net_device *dev_get_by_flags(struct net *net, unsigned short if_flags, | |||
773 | struct net_device *dev, *ret; | 799 | struct net_device *dev, *ret; |
774 | 800 | ||
775 | ret = NULL; | 801 | ret = NULL; |
776 | read_lock(&dev_base_lock); | 802 | rcu_read_lock(); |
777 | for_each_netdev(net, dev) { | 803 | for_each_netdev_rcu(net, dev) { |
778 | if (((dev->flags ^ if_flags) & mask) == 0) { | 804 | if (((dev->flags ^ if_flags) & mask) == 0) { |
779 | dev_hold(dev); | 805 | dev_hold(dev); |
780 | ret = dev; | 806 | ret = dev; |
781 | break; | 807 | break; |
782 | } | 808 | } |
783 | } | 809 | } |
784 | read_unlock(&dev_base_lock); | 810 | rcu_read_unlock(); |
785 | return ret; | 811 | return ret; |
786 | } | 812 | } |
787 | EXPORT_SYMBOL(dev_get_by_flags); | 813 | EXPORT_SYMBOL(dev_get_by_flags); |
@@ -960,7 +986,12 @@ rollback: | |||
960 | 986 | ||
961 | write_lock_bh(&dev_base_lock); | 987 | write_lock_bh(&dev_base_lock); |
962 | hlist_del(&dev->name_hlist); | 988 | hlist_del(&dev->name_hlist); |
963 | hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name)); | 989 | write_unlock_bh(&dev_base_lock); |
990 | |||
991 | synchronize_rcu(); | ||
992 | |||
993 | write_lock_bh(&dev_base_lock); | ||
994 | hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name)); | ||
964 | write_unlock_bh(&dev_base_lock); | 995 | write_unlock_bh(&dev_base_lock); |
965 | 996 | ||
966 | ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev); | 997 | ret = call_netdevice_notifiers(NETDEV_CHANGENAME, dev); |
@@ -1062,9 +1093,9 @@ void dev_load(struct net *net, const char *name) | |||
1062 | { | 1093 | { |
1063 | struct net_device *dev; | 1094 | struct net_device *dev; |
1064 | 1095 | ||
1065 | read_lock(&dev_base_lock); | 1096 | rcu_read_lock(); |
1066 | dev = __dev_get_by_name(net, name); | 1097 | dev = dev_get_by_name_rcu(net, name); |
1067 | read_unlock(&dev_base_lock); | 1098 | rcu_read_unlock(); |
1068 | 1099 | ||
1069 | if (!dev && capable(CAP_NET_ADMIN)) | 1100 | if (!dev && capable(CAP_NET_ADMIN)) |
1070 | request_module("%s", name); | 1101 | request_module("%s", name); |
@@ -3046,18 +3077,18 @@ static int dev_ifconf(struct net *net, char __user *arg) | |||
3046 | * in detail. | 3077 | * in detail. |
3047 | */ | 3078 | */ |
3048 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) | 3079 | void *dev_seq_start(struct seq_file *seq, loff_t *pos) |
3049 | __acquires(dev_base_lock) | 3080 | __acquires(RCU) |
3050 | { | 3081 | { |
3051 | struct net *net = seq_file_net(seq); | 3082 | struct net *net = seq_file_net(seq); |
3052 | loff_t off; | 3083 | loff_t off; |
3053 | struct net_device *dev; | 3084 | struct net_device *dev; |
3054 | 3085 | ||
3055 | read_lock(&dev_base_lock); | 3086 | rcu_read_lock(); |
3056 | if (!*pos) | 3087 | if (!*pos) |
3057 | return SEQ_START_TOKEN; | 3088 | return SEQ_START_TOKEN; |
3058 | 3089 | ||
3059 | off = 1; | 3090 | off = 1; |
3060 | for_each_netdev(net, dev) | 3091 | for_each_netdev_rcu(net, dev) |
3061 | if (off++ == *pos) | 3092 | if (off++ == *pos) |
3062 | return dev; | 3093 | return dev; |
3063 | 3094 | ||
@@ -3066,16 +3097,18 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos) | |||
3066 | 3097 | ||
3067 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 3098 | void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
3068 | { | 3099 | { |
3069 | struct net *net = seq_file_net(seq); | 3100 | struct net_device *dev = (v == SEQ_START_TOKEN) ? |
3101 | first_net_device(seq_file_net(seq)) : | ||
3102 | next_net_device((struct net_device *)v); | ||
3103 | |||
3070 | ++*pos; | 3104 | ++*pos; |
3071 | return v == SEQ_START_TOKEN ? | 3105 | return rcu_dereference(dev); |
3072 | first_net_device(net) : next_net_device((struct net_device *)v); | ||
3073 | } | 3106 | } |
3074 | 3107 | ||
3075 | void dev_seq_stop(struct seq_file *seq, void *v) | 3108 | void dev_seq_stop(struct seq_file *seq, void *v) |
3076 | __releases(dev_base_lock) | 3109 | __releases(RCU) |
3077 | { | 3110 | { |
3078 | read_unlock(&dev_base_lock); | 3111 | rcu_read_unlock(); |
3079 | } | 3112 | } |
3080 | 3113 | ||
3081 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) | 3114 | static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev) |
@@ -4284,12 +4317,12 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) | |||
4284 | EXPORT_SYMBOL(dev_set_mac_address); | 4317 | EXPORT_SYMBOL(dev_set_mac_address); |
4285 | 4318 | ||
4286 | /* | 4319 | /* |
4287 | * Perform the SIOCxIFxxx calls, inside read_lock(dev_base_lock) | 4320 | * Perform the SIOCxIFxxx calls, inside rcu_read_lock() |
4288 | */ | 4321 | */ |
4289 | static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd) | 4322 | static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd) |
4290 | { | 4323 | { |
4291 | int err; | 4324 | int err; |
4292 | struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); | 4325 | struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name); |
4293 | 4326 | ||
4294 | if (!dev) | 4327 | if (!dev) |
4295 | return -ENODEV; | 4328 | return -ENODEV; |
@@ -4521,9 +4554,9 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
4521 | case SIOCGIFINDEX: | 4554 | case SIOCGIFINDEX: |
4522 | case SIOCGIFTXQLEN: | 4555 | case SIOCGIFTXQLEN: |
4523 | dev_load(net, ifr.ifr_name); | 4556 | dev_load(net, ifr.ifr_name); |
4524 | read_lock(&dev_base_lock); | 4557 | rcu_read_lock(); |
4525 | ret = dev_ifsioc_locked(net, &ifr, cmd); | 4558 | ret = dev_ifsioc_locked(net, &ifr, cmd); |
4526 | read_unlock(&dev_base_lock); | 4559 | rcu_read_unlock(); |
4527 | if (!ret) { | 4560 | if (!ret) { |
4528 | if (colon) | 4561 | if (colon) |
4529 | *colon = ':'; | 4562 | *colon = ':'; |
@@ -5227,6 +5260,7 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, | |||
5227 | netdev_init_queues(dev); | 5260 | netdev_init_queues(dev); |
5228 | 5261 | ||
5229 | INIT_LIST_HEAD(&dev->napi_list); | 5262 | INIT_LIST_HEAD(&dev->napi_list); |
5263 | INIT_LIST_HEAD(&dev->unreg_list); | ||
5230 | dev->priv_flags = IFF_XMIT_DST_RELEASE; | 5264 | dev->priv_flags = IFF_XMIT_DST_RELEASE; |
5231 | setup(dev); | 5265 | setup(dev); |
5232 | strcpy(dev->name, name); | 5266 | strcpy(dev->name, name); |
@@ -5308,7 +5342,7 @@ void unregister_netdevice_queue(struct net_device *dev, struct list_head *head) | |||
5308 | ASSERT_RTNL(); | 5342 | ASSERT_RTNL(); |
5309 | 5343 | ||
5310 | if (head) { | 5344 | if (head) { |
5311 | list_add_tail(&dev->unreg_list, head); | 5345 | list_move_tail(&dev->unreg_list, head); |
5312 | } else { | 5346 | } else { |
5313 | rollback_registered(dev); | 5347 | rollback_registered(dev); |
5314 | /* Finish processing unregister after unlock */ | 5348 | /* Finish processing unregister after unlock */ |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 0a113f26bc9f..b8e9d3a86887 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -41,7 +41,7 @@ static void send_dm_alert(struct work_struct *unused); | |||
41 | * netlink alerts | 41 | * netlink alerts |
42 | */ | 42 | */ |
43 | static int trace_state = TRACE_OFF; | 43 | static int trace_state = TRACE_OFF; |
44 | static spinlock_t trace_state_lock = SPIN_LOCK_UNLOCKED; | 44 | static DEFINE_SPINLOCK(trace_state_lock); |
45 | 45 | ||
46 | struct per_cpu_dm_data { | 46 | struct per_cpu_dm_data { |
47 | struct work_struct dm_alert_work; | 47 | struct work_struct dm_alert_work; |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 89de182353b0..157645c0da73 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -544,8 +544,11 @@ int netdev_register_kobject(struct net_device *net) | |||
544 | dev_set_name(dev, "%s", net->name); | 544 | dev_set_name(dev, "%s", net->name); |
545 | 545 | ||
546 | #ifdef CONFIG_SYSFS | 546 | #ifdef CONFIG_SYSFS |
547 | *groups++ = &netstat_group; | 547 | /* Allow for a device specific group */ |
548 | if (*groups) | ||
549 | groups++; | ||
548 | 550 | ||
551 | *groups++ = &netstat_group; | ||
549 | #ifdef CONFIG_WIRELESS_EXT_SYSFS | 552 | #ifdef CONFIG_WIRELESS_EXT_SYSFS |
550 | if (net->ieee80211_ptr) | 553 | if (net->ieee80211_ptr) |
551 | *groups++ = &wireless_group; | 554 | *groups++ = &wireless_group; |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 5ce017bf4afa..d38470a32792 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -340,6 +340,7 @@ struct pktgen_dev { | |||
340 | __u16 cur_udp_src; | 340 | __u16 cur_udp_src; |
341 | __u16 cur_queue_map; | 341 | __u16 cur_queue_map; |
342 | __u32 cur_pkt_size; | 342 | __u32 cur_pkt_size; |
343 | __u32 last_pkt_size; | ||
343 | 344 | ||
344 | __u8 hh[14]; | 345 | __u8 hh[14]; |
345 | /* = { | 346 | /* = { |
@@ -3434,7 +3435,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3434 | pkt_dev->clone_count--; /* back out increment, OOM */ | 3435 | pkt_dev->clone_count--; /* back out increment, OOM */ |
3435 | return; | 3436 | return; |
3436 | } | 3437 | } |
3437 | 3438 | pkt_dev->last_pkt_size = pkt_dev->skb->len; | |
3438 | pkt_dev->allocated_skbs++; | 3439 | pkt_dev->allocated_skbs++; |
3439 | pkt_dev->clone_count = 0; /* reset counter */ | 3440 | pkt_dev->clone_count = 0; /* reset counter */ |
3440 | } | 3441 | } |
@@ -3461,7 +3462,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
3461 | pkt_dev->last_ok = 1; | 3462 | pkt_dev->last_ok = 1; |
3462 | pkt_dev->sofar++; | 3463 | pkt_dev->sofar++; |
3463 | pkt_dev->seq_num++; | 3464 | pkt_dev->seq_num++; |
3464 | pkt_dev->tx_bytes += pkt_dev->cur_pkt_size; | 3465 | pkt_dev->tx_bytes += pkt_dev->last_pkt_size; |
3465 | break; | 3466 | break; |
3466 | default: /* Drivers are not supposed to return other values! */ | 3467 | default: /* Drivers are not supposed to return other values! */ |
3467 | if (net_ratelimit()) | 3468 | if (net_ratelimit()) |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 391a62cd9df6..33148a568199 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -38,7 +38,6 @@ | |||
38 | 38 | ||
39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | 40 | #include <asm/system.h> |
41 | #include <asm/string.h> | ||
42 | 41 | ||
43 | #include <linux/inet.h> | 42 | #include <linux/inet.h> |
44 | #include <linux/netdevice.h> | 43 | #include <linux/netdevice.h> |
@@ -53,8 +52,7 @@ | |||
53 | #include <net/rtnetlink.h> | 52 | #include <net/rtnetlink.h> |
54 | #include <net/net_namespace.h> | 53 | #include <net/net_namespace.h> |
55 | 54 | ||
56 | struct rtnl_link | 55 | struct rtnl_link { |
57 | { | ||
58 | rtnl_doit_func doit; | 56 | rtnl_doit_func doit; |
59 | rtnl_dumpit_func dumpit; | 57 | rtnl_dumpit_func dumpit; |
60 | }; | 58 | }; |
@@ -65,6 +63,7 @@ void rtnl_lock(void) | |||
65 | { | 63 | { |
66 | mutex_lock(&rtnl_mutex); | 64 | mutex_lock(&rtnl_mutex); |
67 | } | 65 | } |
66 | EXPORT_SYMBOL(rtnl_lock); | ||
68 | 67 | ||
69 | void __rtnl_unlock(void) | 68 | void __rtnl_unlock(void) |
70 | { | 69 | { |
@@ -76,16 +75,19 @@ void rtnl_unlock(void) | |||
76 | /* This fellow will unlock it for us. */ | 75 | /* This fellow will unlock it for us. */ |
77 | netdev_run_todo(); | 76 | netdev_run_todo(); |
78 | } | 77 | } |
78 | EXPORT_SYMBOL(rtnl_unlock); | ||
79 | 79 | ||
80 | int rtnl_trylock(void) | 80 | int rtnl_trylock(void) |
81 | { | 81 | { |
82 | return mutex_trylock(&rtnl_mutex); | 82 | return mutex_trylock(&rtnl_mutex); |
83 | } | 83 | } |
84 | EXPORT_SYMBOL(rtnl_trylock); | ||
84 | 85 | ||
85 | int rtnl_is_locked(void) | 86 | int rtnl_is_locked(void) |
86 | { | 87 | { |
87 | return mutex_is_locked(&rtnl_mutex); | 88 | return mutex_is_locked(&rtnl_mutex); |
88 | } | 89 | } |
90 | EXPORT_SYMBOL(rtnl_is_locked); | ||
89 | 91 | ||
90 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 92 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; |
91 | 93 | ||
@@ -168,7 +170,6 @@ int __rtnl_register(int protocol, int msgtype, | |||
168 | 170 | ||
169 | return 0; | 171 | return 0; |
170 | } | 172 | } |
171 | |||
172 | EXPORT_SYMBOL_GPL(__rtnl_register); | 173 | EXPORT_SYMBOL_GPL(__rtnl_register); |
173 | 174 | ||
174 | /** | 175 | /** |
@@ -188,7 +189,6 @@ void rtnl_register(int protocol, int msgtype, | |||
188 | "protocol = %d, message type = %d\n", | 189 | "protocol = %d, message type = %d\n", |
189 | protocol, msgtype); | 190 | protocol, msgtype); |
190 | } | 191 | } |
191 | |||
192 | EXPORT_SYMBOL_GPL(rtnl_register); | 192 | EXPORT_SYMBOL_GPL(rtnl_register); |
193 | 193 | ||
194 | /** | 194 | /** |
@@ -213,7 +213,6 @@ int rtnl_unregister(int protocol, int msgtype) | |||
213 | 213 | ||
214 | return 0; | 214 | return 0; |
215 | } | 215 | } |
216 | |||
217 | EXPORT_SYMBOL_GPL(rtnl_unregister); | 216 | EXPORT_SYMBOL_GPL(rtnl_unregister); |
218 | 217 | ||
219 | /** | 218 | /** |
@@ -230,7 +229,6 @@ void rtnl_unregister_all(int protocol) | |||
230 | kfree(rtnl_msg_handlers[protocol]); | 229 | kfree(rtnl_msg_handlers[protocol]); |
231 | rtnl_msg_handlers[protocol] = NULL; | 230 | rtnl_msg_handlers[protocol] = NULL; |
232 | } | 231 | } |
233 | |||
234 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); | 232 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
235 | 233 | ||
236 | static LIST_HEAD(link_ops); | 234 | static LIST_HEAD(link_ops); |
@@ -253,7 +251,6 @@ int __rtnl_link_register(struct rtnl_link_ops *ops) | |||
253 | list_add_tail(&ops->list, &link_ops); | 251 | list_add_tail(&ops->list, &link_ops); |
254 | return 0; | 252 | return 0; |
255 | } | 253 | } |
256 | |||
257 | EXPORT_SYMBOL_GPL(__rtnl_link_register); | 254 | EXPORT_SYMBOL_GPL(__rtnl_link_register); |
258 | 255 | ||
259 | /** | 256 | /** |
@@ -271,7 +268,6 @@ int rtnl_link_register(struct rtnl_link_ops *ops) | |||
271 | rtnl_unlock(); | 268 | rtnl_unlock(); |
272 | return err; | 269 | return err; |
273 | } | 270 | } |
274 | |||
275 | EXPORT_SYMBOL_GPL(rtnl_link_register); | 271 | EXPORT_SYMBOL_GPL(rtnl_link_register); |
276 | 272 | ||
277 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | 273 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) |
@@ -309,7 +305,6 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
309 | } | 305 | } |
310 | list_del(&ops->list); | 306 | list_del(&ops->list); |
311 | } | 307 | } |
312 | |||
313 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 308 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
314 | 309 | ||
315 | /** | 310 | /** |
@@ -322,7 +317,6 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
322 | __rtnl_link_unregister(ops); | 317 | __rtnl_link_unregister(ops); |
323 | rtnl_unlock(); | 318 | rtnl_unlock(); |
324 | } | 319 | } |
325 | |||
326 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 320 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
327 | 321 | ||
328 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | 322 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) |
@@ -427,12 +421,13 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data | |||
427 | struct rtattr *rta; | 421 | struct rtattr *rta; |
428 | int size = RTA_LENGTH(attrlen); | 422 | int size = RTA_LENGTH(attrlen); |
429 | 423 | ||
430 | rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); | 424 | rta = (struct rtattr *)skb_put(skb, RTA_ALIGN(size)); |
431 | rta->rta_type = attrtype; | 425 | rta->rta_type = attrtype; |
432 | rta->rta_len = size; | 426 | rta->rta_len = size; |
433 | memcpy(RTA_DATA(rta), data, attrlen); | 427 | memcpy(RTA_DATA(rta), data, attrlen); |
434 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); | 428 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); |
435 | } | 429 | } |
430 | EXPORT_SYMBOL(__rta_fill); | ||
436 | 431 | ||
437 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) | 432 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) |
438 | { | 433 | { |
@@ -454,6 +449,7 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) | |||
454 | 449 | ||
455 | return nlmsg_unicast(rtnl, skb, pid); | 450 | return nlmsg_unicast(rtnl, skb, pid); |
456 | } | 451 | } |
452 | EXPORT_SYMBOL(rtnl_unicast); | ||
457 | 453 | ||
458 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | 454 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, |
459 | struct nlmsghdr *nlh, gfp_t flags) | 455 | struct nlmsghdr *nlh, gfp_t flags) |
@@ -466,6 +462,7 @@ void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | |||
466 | 462 | ||
467 | nlmsg_notify(rtnl, skb, pid, group, report, flags); | 463 | nlmsg_notify(rtnl, skb, pid, group, report, flags); |
468 | } | 464 | } |
465 | EXPORT_SYMBOL(rtnl_notify); | ||
469 | 466 | ||
470 | void rtnl_set_sk_err(struct net *net, u32 group, int error) | 467 | void rtnl_set_sk_err(struct net *net, u32 group, int error) |
471 | { | 468 | { |
@@ -473,6 +470,7 @@ void rtnl_set_sk_err(struct net *net, u32 group, int error) | |||
473 | 470 | ||
474 | netlink_set_err(rtnl, 0, group, error); | 471 | netlink_set_err(rtnl, 0, group, error); |
475 | } | 472 | } |
473 | EXPORT_SYMBOL(rtnl_set_sk_err); | ||
476 | 474 | ||
477 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) | 475 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) |
478 | { | 476 | { |
@@ -501,6 +499,7 @@ nla_put_failure: | |||
501 | nla_nest_cancel(skb, mx); | 499 | nla_nest_cancel(skb, mx); |
502 | return -EMSGSIZE; | 500 | return -EMSGSIZE; |
503 | } | 501 | } |
502 | EXPORT_SYMBOL(rtnetlink_put_metrics); | ||
504 | 503 | ||
505 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | 504 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, |
506 | u32 ts, u32 tsage, long expires, u32 error) | 505 | u32 ts, u32 tsage, long expires, u32 error) |
@@ -520,14 +519,13 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | |||
520 | 519 | ||
521 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); | 520 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); |
522 | } | 521 | } |
523 | |||
524 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); | 522 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); |
525 | 523 | ||
526 | static void set_operstate(struct net_device *dev, unsigned char transition) | 524 | static void set_operstate(struct net_device *dev, unsigned char transition) |
527 | { | 525 | { |
528 | unsigned char operstate = dev->operstate; | 526 | unsigned char operstate = dev->operstate; |
529 | 527 | ||
530 | switch(transition) { | 528 | switch (transition) { |
531 | case IF_OPER_UP: | 529 | case IF_OPER_UP: |
532 | if ((operstate == IF_OPER_DORMANT || | 530 | if ((operstate == IF_OPER_DORMANT || |
533 | operstate == IF_OPER_UNKNOWN) && | 531 | operstate == IF_OPER_UNKNOWN) && |
@@ -728,12 +726,27 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
728 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 726 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
729 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 727 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
730 | }; | 728 | }; |
729 | EXPORT_SYMBOL(ifla_policy); | ||
731 | 730 | ||
732 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 731 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
733 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, | 732 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
734 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 733 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
735 | }; | 734 | }; |
736 | 735 | ||
736 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | ||
737 | { | ||
738 | struct net *net; | ||
739 | /* Examine the link attributes and figure out which | ||
740 | * network namespace we are talking about. | ||
741 | */ | ||
742 | if (tb[IFLA_NET_NS_PID]) | ||
743 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
744 | else | ||
745 | net = get_net(src_net); | ||
746 | return net; | ||
747 | } | ||
748 | EXPORT_SYMBOL(rtnl_link_get_net); | ||
749 | |||
737 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | 750 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) |
738 | { | 751 | { |
739 | if (dev) { | 752 | if (dev) { |
@@ -757,8 +770,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
757 | int err; | 770 | int err; |
758 | 771 | ||
759 | if (tb[IFLA_NET_NS_PID]) { | 772 | if (tb[IFLA_NET_NS_PID]) { |
760 | struct net *net; | 773 | struct net *net = rtnl_link_get_net(dev_net(dev), tb); |
761 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
762 | if (IS_ERR(net)) { | 774 | if (IS_ERR(net)) { |
763 | err = PTR_ERR(net); | 775 | err = PTR_ERR(net); |
764 | goto errout; | 776 | goto errout; |
@@ -932,7 +944,8 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
932 | goto errout; | 944 | goto errout; |
933 | } | 945 | } |
934 | 946 | ||
935 | if ((err = validate_linkmsg(dev, tb)) < 0) | 947 | err = validate_linkmsg(dev, tb); |
948 | if (err < 0) | ||
936 | goto errout; | 949 | goto errout; |
937 | 950 | ||
938 | err = do_setlink(dev, ifm, tb, ifname, 0); | 951 | err = do_setlink(dev, ifm, tb, ifname, 0); |
@@ -976,8 +989,8 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
976 | return 0; | 989 | return 0; |
977 | } | 990 | } |
978 | 991 | ||
979 | struct net_device *rtnl_create_link(struct net *net, char *ifname, | 992 | struct net_device *rtnl_create_link(struct net *src_net, struct net *net, |
980 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 993 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) |
981 | { | 994 | { |
982 | int err; | 995 | int err; |
983 | struct net_device *dev; | 996 | struct net_device *dev; |
@@ -985,7 +998,8 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
985 | unsigned int real_num_queues = 1; | 998 | unsigned int real_num_queues = 1; |
986 | 999 | ||
987 | if (ops->get_tx_queues) { | 1000 | if (ops->get_tx_queues) { |
988 | err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues); | 1001 | err = ops->get_tx_queues(src_net, tb, &num_queues, |
1002 | &real_num_queues); | ||
989 | if (err) | 1003 | if (err) |
990 | goto err; | 1004 | goto err; |
991 | } | 1005 | } |
@@ -994,16 +1008,16 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
994 | if (!dev) | 1008 | if (!dev) |
995 | goto err; | 1009 | goto err; |
996 | 1010 | ||
1011 | dev_net_set(dev, net); | ||
1012 | dev->rtnl_link_ops = ops; | ||
997 | dev->real_num_tx_queues = real_num_queues; | 1013 | dev->real_num_tx_queues = real_num_queues; |
1014 | |||
998 | if (strchr(dev->name, '%')) { | 1015 | if (strchr(dev->name, '%')) { |
999 | err = dev_alloc_name(dev, dev->name); | 1016 | err = dev_alloc_name(dev, dev->name); |
1000 | if (err < 0) | 1017 | if (err < 0) |
1001 | goto err_free; | 1018 | goto err_free; |
1002 | } | 1019 | } |
1003 | 1020 | ||
1004 | dev_net_set(dev, net); | ||
1005 | dev->rtnl_link_ops = ops; | ||
1006 | |||
1007 | if (tb[IFLA_MTU]) | 1021 | if (tb[IFLA_MTU]) |
1008 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | 1022 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
1009 | if (tb[IFLA_ADDRESS]) | 1023 | if (tb[IFLA_ADDRESS]) |
@@ -1026,6 +1040,7 @@ err_free: | |||
1026 | err: | 1040 | err: |
1027 | return ERR_PTR(err); | 1041 | return ERR_PTR(err); |
1028 | } | 1042 | } |
1043 | EXPORT_SYMBOL(rtnl_create_link); | ||
1029 | 1044 | ||
1030 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1045 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1031 | { | 1046 | { |
@@ -1059,7 +1074,8 @@ replay: | |||
1059 | else | 1074 | else |
1060 | dev = NULL; | 1075 | dev = NULL; |
1061 | 1076 | ||
1062 | if ((err = validate_linkmsg(dev, tb)) < 0) | 1077 | err = validate_linkmsg(dev, tb); |
1078 | if (err < 0) | ||
1063 | return err; | 1079 | return err; |
1064 | 1080 | ||
1065 | if (tb[IFLA_LINKINFO]) { | 1081 | if (tb[IFLA_LINKINFO]) { |
@@ -1080,6 +1096,7 @@ replay: | |||
1080 | 1096 | ||
1081 | if (1) { | 1097 | if (1) { |
1082 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | 1098 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; |
1099 | struct net *dest_net; | ||
1083 | 1100 | ||
1084 | if (ops) { | 1101 | if (ops) { |
1085 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | 1102 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { |
@@ -1144,17 +1161,19 @@ replay: | |||
1144 | if (!ifname[0]) | 1161 | if (!ifname[0]) |
1145 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 1162 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
1146 | 1163 | ||
1147 | dev = rtnl_create_link(net, ifname, ops, tb); | 1164 | dest_net = rtnl_link_get_net(net, tb); |
1165 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); | ||
1148 | 1166 | ||
1149 | if (IS_ERR(dev)) | 1167 | if (IS_ERR(dev)) |
1150 | err = PTR_ERR(dev); | 1168 | err = PTR_ERR(dev); |
1151 | else if (ops->newlink) | 1169 | else if (ops->newlink) |
1152 | err = ops->newlink(dev, tb, data); | 1170 | err = ops->newlink(net, dev, tb, data); |
1153 | else | 1171 | else |
1154 | err = register_netdevice(dev); | 1172 | err = register_netdevice(dev); |
1155 | |||
1156 | if (err < 0 && !IS_ERR(dev)) | 1173 | if (err < 0 && !IS_ERR(dev)) |
1157 | free_netdev(dev); | 1174 | free_netdev(dev); |
1175 | |||
1176 | put_net(dest_net); | ||
1158 | return err; | 1177 | return err; |
1159 | } | 1178 | } |
1160 | } | 1179 | } |
@@ -1210,7 +1229,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
1210 | 1229 | ||
1211 | if (s_idx == 0) | 1230 | if (s_idx == 0) |
1212 | s_idx = 1; | 1231 | s_idx = 1; |
1213 | for (idx=1; idx<NPROTO; idx++) { | 1232 | for (idx = 1; idx < NPROTO; idx++) { |
1214 | int type = cb->nlh->nlmsg_type-RTM_BASE; | 1233 | int type = cb->nlh->nlmsg_type-RTM_BASE; |
1215 | if (idx < s_idx || idx == PF_PACKET) | 1234 | if (idx < s_idx || idx == PF_PACKET) |
1216 | continue; | 1235 | continue; |
@@ -1277,7 +1296,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1277 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) | 1296 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) |
1278 | return 0; | 1297 | return 0; |
1279 | 1298 | ||
1280 | family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; | 1299 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; |
1281 | if (family >= NPROTO) | 1300 | if (family >= NPROTO) |
1282 | return -EAFNOSUPPORT; | 1301 | return -EAFNOSUPPORT; |
1283 | 1302 | ||
@@ -1310,7 +1329,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1310 | 1329 | ||
1311 | if (nlh->nlmsg_len > min_len) { | 1330 | if (nlh->nlmsg_len > min_len) { |
1312 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | 1331 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); |
1313 | struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len); | 1332 | struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); |
1314 | 1333 | ||
1315 | while (RTA_OK(attr, attrlen)) { | 1334 | while (RTA_OK(attr, attrlen)) { |
1316 | unsigned flavor = attr->rta_type; | 1335 | unsigned flavor = attr->rta_type; |
@@ -1416,14 +1435,3 @@ void __init rtnetlink_init(void) | |||
1416 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); | 1435 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); |
1417 | } | 1436 | } |
1418 | 1437 | ||
1419 | EXPORT_SYMBOL(__rta_fill); | ||
1420 | EXPORT_SYMBOL(rtnetlink_put_metrics); | ||
1421 | EXPORT_SYMBOL(rtnl_lock); | ||
1422 | EXPORT_SYMBOL(rtnl_trylock); | ||
1423 | EXPORT_SYMBOL(rtnl_unlock); | ||
1424 | EXPORT_SYMBOL(rtnl_is_locked); | ||
1425 | EXPORT_SYMBOL(rtnl_unicast); | ||
1426 | EXPORT_SYMBOL(rtnl_notify); | ||
1427 | EXPORT_SYMBOL(rtnl_set_sk_err); | ||
1428 | EXPORT_SYMBOL(rtnl_create_link); | ||
1429 | EXPORT_SYMBOL(ifla_policy); | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 5a51512f638a..76ff58d43e26 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -417,17 +417,18 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen) | |||
417 | if (copy_from_user(devname, optval, optlen)) | 417 | if (copy_from_user(devname, optval, optlen)) |
418 | goto out; | 418 | goto out; |
419 | 419 | ||
420 | if (devname[0] == '\0') { | 420 | index = 0; |
421 | index = 0; | 421 | if (devname[0] != '\0') { |
422 | } else { | 422 | struct net_device *dev; |
423 | struct net_device *dev = dev_get_by_name(net, devname); | 423 | |
424 | 424 | rcu_read_lock(); | |
425 | dev = dev_get_by_name_rcu(net, devname); | ||
426 | if (dev) | ||
427 | index = dev->ifindex; | ||
428 | rcu_read_unlock(); | ||
425 | ret = -ENODEV; | 429 | ret = -ENODEV; |
426 | if (!dev) | 430 | if (!dev) |
427 | goto out; | 431 | goto out; |
428 | |||
429 | index = dev->ifindex; | ||
430 | dev_put(dev); | ||
431 | } | 432 | } |
432 | 433 | ||
433 | lock_sock(sk); | 434 | lock_sock(sk); |
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 00028d4b09d9..2423a0866733 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -991,7 +991,6 @@ static struct inet_protosw dccp_v4_protosw = { | |||
991 | .protocol = IPPROTO_DCCP, | 991 | .protocol = IPPROTO_DCCP, |
992 | .prot = &dccp_v4_prot, | 992 | .prot = &dccp_v4_prot, |
993 | .ops = &inet_dccp_ops, | 993 | .ops = &inet_dccp_ops, |
994 | .capability = -1, | ||
995 | .no_check = 0, | 994 | .no_check = 0, |
996 | .flags = INET_PROTOSW_ICSK, | 995 | .flags = INET_PROTOSW_ICSK, |
997 | }; | 996 | }; |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6d89f9f7d5d8..50ea91a77705 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -1185,7 +1185,6 @@ static struct inet_protosw dccp_v6_protosw = { | |||
1185 | .protocol = IPPROTO_DCCP, | 1185 | .protocol = IPPROTO_DCCP, |
1186 | .prot = &dccp_v6_prot, | 1186 | .prot = &dccp_v6_prot, |
1187 | .ops = &inet6_dccp_ops, | 1187 | .ops = &inet6_dccp_ops, |
1188 | .capability = -1, | ||
1189 | .flags = INET_PROTOSW_ICSK, | 1188 | .flags = INET_PROTOSW_ICSK, |
1190 | }; | 1189 | }; |
1191 | 1190 | ||
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 664965c87e16..9ade3a6de954 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -675,7 +675,8 @@ char *dn_addr2asc(__u16 addr, char *buf) | |||
675 | 675 | ||
676 | 676 | ||
677 | 677 | ||
678 | static int dn_create(struct net *net, struct socket *sock, int protocol) | 678 | static int dn_create(struct net *net, struct socket *sock, int protocol, |
679 | int kern) | ||
679 | { | 680 | { |
680 | struct sock *sk; | 681 | struct sock *sk; |
681 | 682 | ||
@@ -749,9 +750,9 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
749 | 750 | ||
750 | if (!(saddr->sdn_flags & SDF_WILD)) { | 751 | if (!(saddr->sdn_flags & SDF_WILD)) { |
751 | if (le16_to_cpu(saddr->sdn_nodeaddrl)) { | 752 | if (le16_to_cpu(saddr->sdn_nodeaddrl)) { |
752 | read_lock(&dev_base_lock); | 753 | rcu_read_lock(); |
753 | ldev = NULL; | 754 | ldev = NULL; |
754 | for_each_netdev(&init_net, dev) { | 755 | for_each_netdev_rcu(&init_net, dev) { |
755 | if (!dev->dn_ptr) | 756 | if (!dev->dn_ptr) |
756 | continue; | 757 | continue; |
757 | if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) { | 758 | if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) { |
@@ -759,7 +760,7 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
759 | break; | 760 | break; |
760 | } | 761 | } |
761 | } | 762 | } |
762 | read_unlock(&dev_base_lock); | 763 | rcu_read_unlock(); |
763 | if (ldev == NULL) | 764 | if (ldev == NULL) |
764 | return -EADDRNOTAVAIL; | 765 | return -EADDRNOTAVAIL; |
765 | } | 766 | } |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 6e1f085db06a..d82694d930b4 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -600,15 +600,17 @@ static void dn_dev_check_default(struct net_device *dev) | |||
600 | dev_put(dev); | 600 | dev_put(dev); |
601 | } | 601 | } |
602 | 602 | ||
603 | /* | ||
604 | * Called with RTNL | ||
605 | */ | ||
603 | static struct dn_dev *dn_dev_by_index(int ifindex) | 606 | static struct dn_dev *dn_dev_by_index(int ifindex) |
604 | { | 607 | { |
605 | struct net_device *dev; | 608 | struct net_device *dev; |
606 | struct dn_dev *dn_dev = NULL; | 609 | struct dn_dev *dn_dev = NULL; |
607 | dev = dev_get_by_index(&init_net, ifindex); | 610 | |
608 | if (dev) { | 611 | dev = __dev_get_by_index(&init_net, ifindex); |
612 | if (dev) | ||
609 | dn_dev = dev->dn_ptr; | 613 | dn_dev = dev->dn_ptr; |
610 | dev_put(dev); | ||
611 | } | ||
612 | 614 | ||
613 | return dn_dev; | 615 | return dn_dev; |
614 | } | 616 | } |
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c index 27ea2e9b080a..fd641f65e092 100644 --- a/net/decnet/dn_fib.c +++ b/net/decnet/dn_fib.c | |||
@@ -607,8 +607,8 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) | |||
607 | ASSERT_RTNL(); | 607 | ASSERT_RTNL(); |
608 | 608 | ||
609 | /* Scan device list */ | 609 | /* Scan device list */ |
610 | read_lock(&dev_base_lock); | 610 | rcu_read_lock(); |
611 | for_each_netdev(&init_net, dev) { | 611 | for_each_netdev_rcu(&init_net, dev) { |
612 | dn_db = dev->dn_ptr; | 612 | dn_db = dev->dn_ptr; |
613 | if (dn_db == NULL) | 613 | if (dn_db == NULL) |
614 | continue; | 614 | continue; |
@@ -619,7 +619,7 @@ static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa) | |||
619 | } | 619 | } |
620 | } | 620 | } |
621 | } | 621 | } |
622 | read_unlock(&dev_base_lock); | 622 | rcu_read_unlock(); |
623 | 623 | ||
624 | if (found_it == 0) { | 624 | if (found_it == 0) { |
625 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); | 625 | fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa); |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 57662cabaf9b..860286a3921b 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -908,8 +908,8 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old | |||
908 | dev_put(dev_out); | 908 | dev_put(dev_out); |
909 | goto out; | 909 | goto out; |
910 | } | 910 | } |
911 | read_lock(&dev_base_lock); | 911 | rcu_read_lock(); |
912 | for_each_netdev(&init_net, dev) { | 912 | for_each_netdev_rcu(&init_net, dev) { |
913 | if (!dev->dn_ptr) | 913 | if (!dev->dn_ptr) |
914 | continue; | 914 | continue; |
915 | if (!dn_dev_islocal(dev, oldflp->fld_src)) | 915 | if (!dn_dev_islocal(dev, oldflp->fld_src)) |
@@ -922,7 +922,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowi *old | |||
922 | dev_out = dev; | 922 | dev_out = dev; |
923 | break; | 923 | break; |
924 | } | 924 | } |
925 | read_unlock(&dev_base_lock); | 925 | rcu_read_unlock(); |
926 | if (dev_out == NULL) | 926 | if (dev_out == NULL) |
927 | goto out; | 927 | goto out; |
928 | dev_hold(dev_out); | 928 | dev_hold(dev_out); |
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index 26b0ab1e9f56..2036568beea9 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c | |||
@@ -263,11 +263,10 @@ static int dn_def_dev_strategy(ctl_table *table, | |||
263 | return -ENODEV; | 263 | return -ENODEV; |
264 | 264 | ||
265 | rv = -ENODEV; | 265 | rv = -ENODEV; |
266 | if (dev->dn_ptr != NULL) { | 266 | if (dev->dn_ptr != NULL) |
267 | rv = dn_dev_set_default(dev, 1); | 267 | rv = dn_dev_set_default(dev, 1); |
268 | if (rv) | 268 | if (rv) |
269 | dev_put(dev); | 269 | dev_put(dev); |
270 | } | ||
271 | } | 270 | } |
272 | 271 | ||
273 | return rv; | 272 | return rv; |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 5e9426a11c3e..596679803de5 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -605,7 +605,8 @@ static struct proto econet_proto = { | |||
605 | * Create an Econet socket | 605 | * Create an Econet socket |
606 | */ | 606 | */ |
607 | 607 | ||
608 | static int econet_create(struct net *net, struct socket *sock, int protocol) | 608 | static int econet_create(struct net *net, struct socket *sock, int protocol, |
609 | int kern) | ||
609 | { | 610 | { |
610 | struct sock *sk; | 611 | struct sock *sk; |
611 | struct econet_sock *eo; | 612 | struct econet_sock *eo; |
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index 4068a9f5113e..ce2d33582859 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_IEEE802154) += nl802154.o af_802154.o wpan-class.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
2 | nl802154-y := netlink.o nl_policy.o | 2 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o |
3 | af_802154-y := af_ieee802154.o raw.o dgram.o | 3 | af_802154-y := af_ieee802154.o raw.o dgram.o |
4 | 4 | ||
5 | ccflags-y += -Wall -DDEBUG | 5 | ccflags-y += -Wall -DDEBUG |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 309348fba72b..de6e34d2a7f8 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
@@ -234,7 +234,7 @@ static const struct proto_ops ieee802154_dgram_ops = { | |||
234 | * set the state. | 234 | * set the state. |
235 | */ | 235 | */ |
236 | static int ieee802154_create(struct net *net, struct socket *sock, | 236 | static int ieee802154_create(struct net *net, struct socket *sock, |
237 | int protocol) | 237 | int protocol, int kern) |
238 | { | 238 | { |
239 | struct sock *sk; | 239 | struct sock *sk; |
240 | int rc; | 240 | int rc; |
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h new file mode 100644 index 000000000000..aadec428e6ec --- /dev/null +++ b/net/ieee802154/ieee802154.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007, 2008, 2009 Siemens AG | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 | ||
6 | * as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
16 | * | ||
17 | */ | ||
18 | #ifndef IEEE_802154_LOCAL_H | ||
19 | #define IEEE_802154_LOCAL_H | ||
20 | |||
21 | int __init ieee802154_nl_init(void); | ||
22 | void __exit ieee802154_nl_exit(void); | ||
23 | |||
24 | #define IEEE802154_OP(_cmd, _func) \ | ||
25 | { \ | ||
26 | .cmd = _cmd, \ | ||
27 | .policy = ieee802154_policy, \ | ||
28 | .doit = _func, \ | ||
29 | .dumpit = NULL, \ | ||
30 | .flags = GENL_ADMIN_PERM, \ | ||
31 | } | ||
32 | |||
33 | #define IEEE802154_DUMP(_cmd, _func, _dump) \ | ||
34 | { \ | ||
35 | .cmd = _cmd, \ | ||
36 | .policy = ieee802154_policy, \ | ||
37 | .doit = _func, \ | ||
38 | .dumpit = _dump, \ | ||
39 | } | ||
40 | |||
41 | struct genl_info; | ||
42 | |||
43 | struct sk_buff *ieee802154_nl_create(int flags, u8 req); | ||
44 | int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group); | ||
45 | struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, | ||
46 | int flags, u8 req); | ||
47 | int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info); | ||
48 | |||
49 | extern struct genl_family nl802154_family; | ||
50 | int nl802154_mac_register(void); | ||
51 | int nl802154_phy_register(void); | ||
52 | |||
53 | #endif | ||
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index ca767bde17a4..33137b99e471 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c | |||
@@ -23,21 +23,15 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/if_arp.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <net/netlink.h> | ||
29 | #include <net/genetlink.h> | 26 | #include <net/genetlink.h> |
30 | #include <net/sock.h> | ||
31 | #include <linux/nl802154.h> | 27 | #include <linux/nl802154.h> |
32 | #include <net/af_ieee802154.h> | 28 | |
33 | #include <net/nl802154.h> | 29 | #include "ieee802154.h" |
34 | #include <net/ieee802154.h> | ||
35 | #include <net/ieee802154_netdev.h> | ||
36 | 30 | ||
37 | static unsigned int ieee802154_seq_num; | 31 | static unsigned int ieee802154_seq_num; |
38 | static DEFINE_SPINLOCK(ieee802154_seq_lock); | 32 | static DEFINE_SPINLOCK(ieee802154_seq_lock); |
39 | 33 | ||
40 | static struct genl_family ieee802154_coordinator_family = { | 34 | struct genl_family nl802154_family = { |
41 | .id = GENL_ID_GENERATE, | 35 | .id = GENL_ID_GENERATE, |
42 | .hdrsize = 0, | 36 | .hdrsize = 0, |
43 | .name = IEEE802154_NL_NAME, | 37 | .name = IEEE802154_NL_NAME, |
@@ -45,16 +39,8 @@ static struct genl_family ieee802154_coordinator_family = { | |||
45 | .maxattr = IEEE802154_ATTR_MAX, | 39 | .maxattr = IEEE802154_ATTR_MAX, |
46 | }; | 40 | }; |
47 | 41 | ||
48 | static struct genl_multicast_group ieee802154_coord_mcgrp = { | ||
49 | .name = IEEE802154_MCAST_COORD_NAME, | ||
50 | }; | ||
51 | |||
52 | static struct genl_multicast_group ieee802154_beacon_mcgrp = { | ||
53 | .name = IEEE802154_MCAST_BEACON_NAME, | ||
54 | }; | ||
55 | |||
56 | /* Requests to userspace */ | 42 | /* Requests to userspace */ |
57 | static struct sk_buff *ieee802154_nl_create(int flags, u8 req) | 43 | struct sk_buff *ieee802154_nl_create(int flags, u8 req) |
58 | { | 44 | { |
59 | void *hdr; | 45 | void *hdr; |
60 | struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 46 | struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); |
@@ -65,7 +51,7 @@ static struct sk_buff *ieee802154_nl_create(int flags, u8 req) | |||
65 | 51 | ||
66 | spin_lock_irqsave(&ieee802154_seq_lock, f); | 52 | spin_lock_irqsave(&ieee802154_seq_lock, f); |
67 | hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, | 53 | hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, |
68 | &ieee802154_coordinator_family, flags, req); | 54 | &nl802154_family, flags, req); |
69 | spin_unlock_irqrestore(&ieee802154_seq_lock, f); | 55 | spin_unlock_irqrestore(&ieee802154_seq_lock, f); |
70 | if (!hdr) { | 56 | if (!hdr) { |
71 | nlmsg_free(msg); | 57 | nlmsg_free(msg); |
@@ -75,7 +61,7 @@ static struct sk_buff *ieee802154_nl_create(int flags, u8 req) | |||
75 | return msg; | 61 | return msg; |
76 | } | 62 | } |
77 | 63 | ||
78 | static int ieee802154_nl_finish(struct sk_buff *msg) | 64 | int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group) |
79 | { | 65 | { |
80 | /* XXX: nlh is right at the start of msg */ | 66 | /* XXX: nlh is right at the start of msg */ |
81 | void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); | 67 | void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); |
@@ -83,607 +69,70 @@ static int ieee802154_nl_finish(struct sk_buff *msg) | |||
83 | if (genlmsg_end(msg, hdr) < 0) | 69 | if (genlmsg_end(msg, hdr) < 0) |
84 | goto out; | 70 | goto out; |
85 | 71 | ||
86 | return genlmsg_multicast(msg, 0, ieee802154_coord_mcgrp.id, | 72 | return genlmsg_multicast(msg, 0, group, GFP_ATOMIC); |
87 | GFP_ATOMIC); | ||
88 | out: | 73 | out: |
89 | nlmsg_free(msg); | 74 | nlmsg_free(msg); |
90 | return -ENOBUFS; | 75 | return -ENOBUFS; |
91 | } | 76 | } |
92 | 77 | ||
93 | int ieee802154_nl_assoc_indic(struct net_device *dev, | 78 | struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, |
94 | struct ieee802154_addr *addr, u8 cap) | 79 | int flags, u8 req) |
95 | { | ||
96 | struct sk_buff *msg; | ||
97 | |||
98 | pr_debug("%s\n", __func__); | ||
99 | |||
100 | if (addr->addr_type != IEEE802154_ADDR_LONG) { | ||
101 | pr_err("%s: received non-long source address!\n", __func__); | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | |||
105 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); | ||
106 | if (!msg) | ||
107 | return -ENOBUFS; | ||
108 | |||
109 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
110 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
111 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
112 | dev->dev_addr); | ||
113 | |||
114 | NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | ||
115 | addr->hwaddr); | ||
116 | |||
117 | NLA_PUT_U8(msg, IEEE802154_ATTR_CAPABILITY, cap); | ||
118 | |||
119 | return ieee802154_nl_finish(msg); | ||
120 | |||
121 | nla_put_failure: | ||
122 | nlmsg_free(msg); | ||
123 | return -ENOBUFS; | ||
124 | } | ||
125 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); | ||
126 | |||
127 | int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, | ||
128 | u8 status) | ||
129 | { | ||
130 | struct sk_buff *msg; | ||
131 | |||
132 | pr_debug("%s\n", __func__); | ||
133 | |||
134 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF); | ||
135 | if (!msg) | ||
136 | return -ENOBUFS; | ||
137 | |||
138 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
139 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
140 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
141 | dev->dev_addr); | ||
142 | |||
143 | NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr); | ||
144 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
145 | |||
146 | return ieee802154_nl_finish(msg); | ||
147 | |||
148 | nla_put_failure: | ||
149 | nlmsg_free(msg); | ||
150 | return -ENOBUFS; | ||
151 | } | ||
152 | EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); | ||
153 | |||
154 | int ieee802154_nl_disassoc_indic(struct net_device *dev, | ||
155 | struct ieee802154_addr *addr, u8 reason) | ||
156 | { | ||
157 | struct sk_buff *msg; | ||
158 | |||
159 | pr_debug("%s\n", __func__); | ||
160 | |||
161 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); | ||
162 | if (!msg) | ||
163 | return -ENOBUFS; | ||
164 | |||
165 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
166 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
167 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
168 | dev->dev_addr); | ||
169 | |||
170 | if (addr->addr_type == IEEE802154_ADDR_LONG) | ||
171 | NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | ||
172 | addr->hwaddr); | ||
173 | else | ||
174 | NLA_PUT_U16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, | ||
175 | addr->short_addr); | ||
176 | |||
177 | NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason); | ||
178 | |||
179 | return ieee802154_nl_finish(msg); | ||
180 | |||
181 | nla_put_failure: | ||
182 | nlmsg_free(msg); | ||
183 | return -ENOBUFS; | ||
184 | } | ||
185 | EXPORT_SYMBOL(ieee802154_nl_disassoc_indic); | ||
186 | |||
187 | int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) | ||
188 | { | ||
189 | struct sk_buff *msg; | ||
190 | |||
191 | pr_debug("%s\n", __func__); | ||
192 | |||
193 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF); | ||
194 | if (!msg) | ||
195 | return -ENOBUFS; | ||
196 | |||
197 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
198 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
199 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
200 | dev->dev_addr); | ||
201 | |||
202 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
203 | |||
204 | return ieee802154_nl_finish(msg); | ||
205 | |||
206 | nla_put_failure: | ||
207 | nlmsg_free(msg); | ||
208 | return -ENOBUFS; | ||
209 | } | ||
210 | EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); | ||
211 | |||
212 | int ieee802154_nl_beacon_indic(struct net_device *dev, | ||
213 | u16 panid, u16 coord_addr) | ||
214 | { | ||
215 | struct sk_buff *msg; | ||
216 | |||
217 | pr_debug("%s\n", __func__); | ||
218 | |||
219 | msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); | ||
220 | if (!msg) | ||
221 | return -ENOBUFS; | ||
222 | |||
223 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
224 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
225 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
226 | dev->dev_addr); | ||
227 | NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr); | ||
228 | NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid); | ||
229 | |||
230 | return ieee802154_nl_finish(msg); | ||
231 | |||
232 | nla_put_failure: | ||
233 | nlmsg_free(msg); | ||
234 | return -ENOBUFS; | ||
235 | } | ||
236 | EXPORT_SYMBOL(ieee802154_nl_beacon_indic); | ||
237 | |||
238 | int ieee802154_nl_scan_confirm(struct net_device *dev, | ||
239 | u8 status, u8 scan_type, u32 unscanned, u8 page, | ||
240 | u8 *edl/* , struct list_head *pan_desc_list */) | ||
241 | { | ||
242 | struct sk_buff *msg; | ||
243 | |||
244 | pr_debug("%s\n", __func__); | ||
245 | |||
246 | msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF); | ||
247 | if (!msg) | ||
248 | return -ENOBUFS; | ||
249 | |||
250 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
251 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
252 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
253 | dev->dev_addr); | ||
254 | |||
255 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
256 | NLA_PUT_U8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type); | ||
257 | NLA_PUT_U32(msg, IEEE802154_ATTR_CHANNELS, unscanned); | ||
258 | NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, page); | ||
259 | |||
260 | if (edl) | ||
261 | NLA_PUT(msg, IEEE802154_ATTR_ED_LIST, 27, edl); | ||
262 | |||
263 | return ieee802154_nl_finish(msg); | ||
264 | |||
265 | nla_put_failure: | ||
266 | nlmsg_free(msg); | ||
267 | return -ENOBUFS; | ||
268 | } | ||
269 | EXPORT_SYMBOL(ieee802154_nl_scan_confirm); | ||
270 | |||
271 | int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) | ||
272 | { | ||
273 | struct sk_buff *msg; | ||
274 | |||
275 | pr_debug("%s\n", __func__); | ||
276 | |||
277 | msg = ieee802154_nl_create(0, IEEE802154_START_CONF); | ||
278 | if (!msg) | ||
279 | return -ENOBUFS; | ||
280 | |||
281 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
282 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
283 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
284 | dev->dev_addr); | ||
285 | |||
286 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
287 | |||
288 | return ieee802154_nl_finish(msg); | ||
289 | |||
290 | nla_put_failure: | ||
291 | nlmsg_free(msg); | ||
292 | return -ENOBUFS; | ||
293 | } | ||
294 | EXPORT_SYMBOL(ieee802154_nl_start_confirm); | ||
295 | |||
296 | static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, | ||
297 | u32 seq, int flags, struct net_device *dev) | ||
298 | { | 80 | { |
299 | void *hdr; | 81 | void *hdr; |
82 | struct sk_buff *msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | ||
300 | 83 | ||
301 | pr_debug("%s\n", __func__); | 84 | if (!msg) |
302 | |||
303 | hdr = genlmsg_put(msg, 0, seq, &ieee802154_coordinator_family, flags, | ||
304 | IEEE802154_LIST_IFACE); | ||
305 | if (!hdr) | ||
306 | goto out; | ||
307 | |||
308 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
309 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
310 | |||
311 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
312 | dev->dev_addr); | ||
313 | NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, | ||
314 | ieee802154_mlme_ops(dev)->get_short_addr(dev)); | ||
315 | NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, | ||
316 | ieee802154_mlme_ops(dev)->get_pan_id(dev)); | ||
317 | return genlmsg_end(msg, hdr); | ||
318 | |||
319 | nla_put_failure: | ||
320 | genlmsg_cancel(msg, hdr); | ||
321 | out: | ||
322 | return -EMSGSIZE; | ||
323 | } | ||
324 | |||
325 | /* Requests from userspace */ | ||
326 | static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) | ||
327 | { | ||
328 | struct net_device *dev; | ||
329 | |||
330 | if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { | ||
331 | char name[IFNAMSIZ + 1]; | ||
332 | nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], | ||
333 | sizeof(name)); | ||
334 | dev = dev_get_by_name(&init_net, name); | ||
335 | } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) | ||
336 | dev = dev_get_by_index(&init_net, | ||
337 | nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); | ||
338 | else | ||
339 | return NULL; | ||
340 | |||
341 | if (!dev) | ||
342 | return NULL; | 85 | return NULL; |
343 | 86 | ||
344 | if (dev->type != ARPHRD_IEEE802154) { | 87 | hdr = genlmsg_put_reply(msg, info, |
345 | dev_put(dev); | 88 | &nl802154_family, flags, req); |
89 | if (!hdr) { | ||
90 | nlmsg_free(msg); | ||
346 | return NULL; | 91 | return NULL; |
347 | } | 92 | } |
348 | 93 | ||
349 | return dev; | 94 | return msg; |
350 | } | ||
351 | |||
352 | static int ieee802154_associate_req(struct sk_buff *skb, | ||
353 | struct genl_info *info) | ||
354 | { | ||
355 | struct net_device *dev; | ||
356 | struct ieee802154_addr addr; | ||
357 | u8 page; | ||
358 | int ret = -EINVAL; | ||
359 | |||
360 | if (!info->attrs[IEEE802154_ATTR_CHANNEL] || | ||
361 | !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || | ||
362 | (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] && | ||
363 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) || | ||
364 | !info->attrs[IEEE802154_ATTR_CAPABILITY]) | ||
365 | return -EINVAL; | ||
366 | |||
367 | dev = ieee802154_nl_get_dev(info); | ||
368 | if (!dev) | ||
369 | return -ENODEV; | ||
370 | |||
371 | if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { | ||
372 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
373 | nla_memcpy(addr.hwaddr, | ||
374 | info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], | ||
375 | IEEE802154_ADDR_LEN); | ||
376 | } else { | ||
377 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
378 | addr.short_addr = nla_get_u16( | ||
379 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | ||
380 | } | ||
381 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
382 | |||
383 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
384 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
385 | else | ||
386 | page = 0; | ||
387 | |||
388 | ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr, | ||
389 | nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]), | ||
390 | page, | ||
391 | nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); | ||
392 | |||
393 | dev_put(dev); | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | static int ieee802154_associate_resp(struct sk_buff *skb, | ||
398 | struct genl_info *info) | ||
399 | { | ||
400 | struct net_device *dev; | ||
401 | struct ieee802154_addr addr; | ||
402 | int ret = -EINVAL; | ||
403 | |||
404 | if (!info->attrs[IEEE802154_ATTR_STATUS] || | ||
405 | !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || | ||
406 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) | ||
407 | return -EINVAL; | ||
408 | |||
409 | dev = ieee802154_nl_get_dev(info); | ||
410 | if (!dev) | ||
411 | return -ENODEV; | ||
412 | |||
413 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
414 | nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | ||
415 | IEEE802154_ADDR_LEN); | ||
416 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | ||
417 | |||
418 | |||
419 | ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, | ||
420 | nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), | ||
421 | nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); | ||
422 | |||
423 | dev_put(dev); | ||
424 | return ret; | ||
425 | } | ||
426 | |||
427 | static int ieee802154_disassociate_req(struct sk_buff *skb, | ||
428 | struct genl_info *info) | ||
429 | { | ||
430 | struct net_device *dev; | ||
431 | struct ieee802154_addr addr; | ||
432 | int ret = -EINVAL; | ||
433 | |||
434 | if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && | ||
435 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || | ||
436 | !info->attrs[IEEE802154_ATTR_REASON]) | ||
437 | return -EINVAL; | ||
438 | |||
439 | dev = ieee802154_nl_get_dev(info); | ||
440 | if (!dev) | ||
441 | return -ENODEV; | ||
442 | |||
443 | if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { | ||
444 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
445 | nla_memcpy(addr.hwaddr, | ||
446 | info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | ||
447 | IEEE802154_ADDR_LEN); | ||
448 | } else { | ||
449 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
450 | addr.short_addr = nla_get_u16( | ||
451 | info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); | ||
452 | } | ||
453 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | ||
454 | |||
455 | ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, | ||
456 | nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); | ||
457 | |||
458 | dev_put(dev); | ||
459 | return ret; | ||
460 | } | ||
461 | |||
462 | /* | ||
463 | * PANid, channel, beacon_order = 15, superframe_order = 15, | ||
464 | * PAN_coordinator, battery_life_extension = 0, | ||
465 | * coord_realignment = 0, security_enable = 0 | ||
466 | */ | ||
467 | static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | ||
468 | { | ||
469 | struct net_device *dev; | ||
470 | struct ieee802154_addr addr; | ||
471 | |||
472 | u8 channel, bcn_ord, sf_ord; | ||
473 | u8 page; | ||
474 | int pan_coord, blx, coord_realign; | ||
475 | int ret; | ||
476 | |||
477 | if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || | ||
478 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || | ||
479 | !info->attrs[IEEE802154_ATTR_CHANNEL] || | ||
480 | !info->attrs[IEEE802154_ATTR_BCN_ORD] || | ||
481 | !info->attrs[IEEE802154_ATTR_SF_ORD] || | ||
482 | !info->attrs[IEEE802154_ATTR_PAN_COORD] || | ||
483 | !info->attrs[IEEE802154_ATTR_BAT_EXT] || | ||
484 | !info->attrs[IEEE802154_ATTR_COORD_REALIGN] | ||
485 | ) | ||
486 | return -EINVAL; | ||
487 | |||
488 | dev = ieee802154_nl_get_dev(info); | ||
489 | if (!dev) | ||
490 | return -ENODEV; | ||
491 | |||
492 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
493 | addr.short_addr = nla_get_u16( | ||
494 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | ||
495 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
496 | |||
497 | channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); | ||
498 | bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); | ||
499 | sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]); | ||
500 | pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]); | ||
501 | blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); | ||
502 | coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); | ||
503 | |||
504 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
505 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
506 | else | ||
507 | page = 0; | ||
508 | |||
509 | |||
510 | if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { | ||
511 | ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); | ||
512 | dev_put(dev); | ||
513 | return -EINVAL; | ||
514 | } | ||
515 | |||
516 | ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, | ||
517 | bcn_ord, sf_ord, pan_coord, blx, coord_realign); | ||
518 | |||
519 | dev_put(dev); | ||
520 | return ret; | ||
521 | } | ||
522 | |||
523 | static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) | ||
524 | { | ||
525 | struct net_device *dev; | ||
526 | int ret; | ||
527 | u8 type; | ||
528 | u32 channels; | ||
529 | u8 duration; | ||
530 | u8 page; | ||
531 | |||
532 | if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || | ||
533 | !info->attrs[IEEE802154_ATTR_CHANNELS] || | ||
534 | !info->attrs[IEEE802154_ATTR_DURATION]) | ||
535 | return -EINVAL; | ||
536 | |||
537 | dev = ieee802154_nl_get_dev(info); | ||
538 | if (!dev) | ||
539 | return -ENODEV; | ||
540 | |||
541 | type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); | ||
542 | channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); | ||
543 | duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); | ||
544 | |||
545 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
546 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
547 | else | ||
548 | page = 0; | ||
549 | |||
550 | |||
551 | ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, | ||
552 | duration); | ||
553 | |||
554 | dev_put(dev); | ||
555 | return ret; | ||
556 | } | 95 | } |
557 | 96 | ||
558 | static int ieee802154_list_iface(struct sk_buff *skb, | 97 | int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info) |
559 | struct genl_info *info) | ||
560 | { | 98 | { |
561 | /* Request for interface name, index, type, IEEE address, | 99 | /* XXX: nlh is right at the start of msg */ |
562 | PAN Id, short address */ | 100 | void *hdr = genlmsg_data(NLMSG_DATA(msg->data)); |
563 | struct sk_buff *msg; | ||
564 | struct net_device *dev = NULL; | ||
565 | int rc = -ENOBUFS; | ||
566 | |||
567 | pr_debug("%s\n", __func__); | ||
568 | |||
569 | dev = ieee802154_nl_get_dev(info); | ||
570 | if (!dev) | ||
571 | return -ENODEV; | ||
572 | |||
573 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
574 | if (!msg) | ||
575 | goto out_dev; | ||
576 | |||
577 | rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq, | ||
578 | 0, dev); | ||
579 | if (rc < 0) | ||
580 | goto out_free; | ||
581 | 101 | ||
582 | dev_put(dev); | 102 | if (genlmsg_end(msg, hdr) < 0) |
103 | goto out; | ||
583 | 104 | ||
584 | return genlmsg_unicast(&init_net, msg, info->snd_pid); | 105 | return genlmsg_reply(msg, info); |
585 | out_free: | 106 | out: |
586 | nlmsg_free(msg); | 107 | nlmsg_free(msg); |
587 | out_dev: | 108 | return -ENOBUFS; |
588 | dev_put(dev); | ||
589 | return rc; | ||
590 | |||
591 | } | ||
592 | |||
593 | static int ieee802154_dump_iface(struct sk_buff *skb, | ||
594 | struct netlink_callback *cb) | ||
595 | { | ||
596 | struct net *net = sock_net(skb->sk); | ||
597 | struct net_device *dev; | ||
598 | int idx; | ||
599 | int s_idx = cb->args[0]; | ||
600 | |||
601 | pr_debug("%s\n", __func__); | ||
602 | |||
603 | idx = 0; | ||
604 | for_each_netdev(net, dev) { | ||
605 | if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) | ||
606 | goto cont; | ||
607 | |||
608 | if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid, | ||
609 | cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) | ||
610 | break; | ||
611 | cont: | ||
612 | idx++; | ||
613 | } | ||
614 | cb->args[0] = idx; | ||
615 | |||
616 | return skb->len; | ||
617 | } | 109 | } |
618 | 110 | ||
619 | #define IEEE802154_OP(_cmd, _func) \ | 111 | int __init ieee802154_nl_init(void) |
620 | { \ | ||
621 | .cmd = _cmd, \ | ||
622 | .policy = ieee802154_policy, \ | ||
623 | .doit = _func, \ | ||
624 | .dumpit = NULL, \ | ||
625 | .flags = GENL_ADMIN_PERM, \ | ||
626 | } | ||
627 | |||
628 | #define IEEE802154_DUMP(_cmd, _func, _dump) \ | ||
629 | { \ | ||
630 | .cmd = _cmd, \ | ||
631 | .policy = ieee802154_policy, \ | ||
632 | .doit = _func, \ | ||
633 | .dumpit = _dump, \ | ||
634 | } | ||
635 | |||
636 | static struct genl_ops ieee802154_coordinator_ops[] = { | ||
637 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), | ||
638 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), | ||
639 | IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), | ||
640 | IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), | ||
641 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), | ||
642 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, | ||
643 | ieee802154_dump_iface), | ||
644 | }; | ||
645 | |||
646 | static int __init ieee802154_nl_init(void) | ||
647 | { | 112 | { |
648 | int rc; | 113 | int rc; |
649 | int i; | ||
650 | 114 | ||
651 | rc = genl_register_family(&ieee802154_coordinator_family); | 115 | rc = genl_register_family(&nl802154_family); |
652 | if (rc) | 116 | if (rc) |
653 | goto fail; | 117 | goto fail; |
654 | 118 | ||
655 | rc = genl_register_mc_group(&ieee802154_coordinator_family, | 119 | rc = nl802154_mac_register(); |
656 | &ieee802154_coord_mcgrp); | ||
657 | if (rc) | 120 | if (rc) |
658 | goto fail; | 121 | goto fail; |
659 | 122 | ||
660 | rc = genl_register_mc_group(&ieee802154_coordinator_family, | 123 | rc = nl802154_phy_register(); |
661 | &ieee802154_beacon_mcgrp); | ||
662 | if (rc) | 124 | if (rc) |
663 | goto fail; | 125 | goto fail; |
664 | 126 | ||
665 | |||
666 | for (i = 0; i < ARRAY_SIZE(ieee802154_coordinator_ops); i++) { | ||
667 | rc = genl_register_ops(&ieee802154_coordinator_family, | ||
668 | &ieee802154_coordinator_ops[i]); | ||
669 | if (rc) | ||
670 | goto fail; | ||
671 | } | ||
672 | |||
673 | return 0; | 127 | return 0; |
674 | 128 | ||
675 | fail: | 129 | fail: |
676 | genl_unregister_family(&ieee802154_coordinator_family); | 130 | genl_unregister_family(&nl802154_family); |
677 | return rc; | 131 | return rc; |
678 | } | 132 | } |
679 | module_init(ieee802154_nl_init); | ||
680 | 133 | ||
681 | static void __exit ieee802154_nl_exit(void) | 134 | void __exit ieee802154_nl_exit(void) |
682 | { | 135 | { |
683 | genl_unregister_family(&ieee802154_coordinator_family); | 136 | genl_unregister_family(&nl802154_family); |
684 | } | 137 | } |
685 | module_exit(ieee802154_nl_exit); | ||
686 | |||
687 | MODULE_LICENSE("GPL v2"); | ||
688 | MODULE_DESCRIPTION("ieee 802.15.4 configuration interface"); | ||
689 | 138 | ||
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c new file mode 100644 index 000000000000..135c1678fb11 --- /dev/null +++ b/net/ieee802154/nl-mac.c | |||
@@ -0,0 +1,617 @@ | |||
1 | /* | ||
2 | * Netlink inteface for IEEE 802.15.4 stack | ||
3 | * | ||
4 | * Copyright 2007, 2008 Siemens AG | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * Written by: | ||
20 | * Sergey Lapin <slapin@ossfans.org> | ||
21 | * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | ||
22 | * Maxim Osipov <maxim.osipov@siemens.com> | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/if_arp.h> | ||
27 | #include <linux/netdevice.h> | ||
28 | #include <net/netlink.h> | ||
29 | #include <net/genetlink.h> | ||
30 | #include <net/sock.h> | ||
31 | #include <linux/nl802154.h> | ||
32 | #include <net/af_ieee802154.h> | ||
33 | #include <net/nl802154.h> | ||
34 | #include <net/ieee802154.h> | ||
35 | #include <net/ieee802154_netdev.h> | ||
36 | #include <net/wpan-phy.h> | ||
37 | |||
38 | #include "ieee802154.h" | ||
39 | |||
40 | static struct genl_multicast_group ieee802154_coord_mcgrp = { | ||
41 | .name = IEEE802154_MCAST_COORD_NAME, | ||
42 | }; | ||
43 | |||
44 | static struct genl_multicast_group ieee802154_beacon_mcgrp = { | ||
45 | .name = IEEE802154_MCAST_BEACON_NAME, | ||
46 | }; | ||
47 | |||
48 | int ieee802154_nl_assoc_indic(struct net_device *dev, | ||
49 | struct ieee802154_addr *addr, u8 cap) | ||
50 | { | ||
51 | struct sk_buff *msg; | ||
52 | |||
53 | pr_debug("%s\n", __func__); | ||
54 | |||
55 | if (addr->addr_type != IEEE802154_ADDR_LONG) { | ||
56 | pr_err("%s: received non-long source address!\n", __func__); | ||
57 | return -EINVAL; | ||
58 | } | ||
59 | |||
60 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC); | ||
61 | if (!msg) | ||
62 | return -ENOBUFS; | ||
63 | |||
64 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
65 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
66 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
67 | dev->dev_addr); | ||
68 | |||
69 | NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | ||
70 | addr->hwaddr); | ||
71 | |||
72 | NLA_PUT_U8(msg, IEEE802154_ATTR_CAPABILITY, cap); | ||
73 | |||
74 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
75 | |||
76 | nla_put_failure: | ||
77 | nlmsg_free(msg); | ||
78 | return -ENOBUFS; | ||
79 | } | ||
80 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); | ||
81 | |||
82 | int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, | ||
83 | u8 status) | ||
84 | { | ||
85 | struct sk_buff *msg; | ||
86 | |||
87 | pr_debug("%s\n", __func__); | ||
88 | |||
89 | msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF); | ||
90 | if (!msg) | ||
91 | return -ENOBUFS; | ||
92 | |||
93 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
94 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
95 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
96 | dev->dev_addr); | ||
97 | |||
98 | NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr); | ||
99 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
100 | |||
101 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
102 | |||
103 | nla_put_failure: | ||
104 | nlmsg_free(msg); | ||
105 | return -ENOBUFS; | ||
106 | } | ||
107 | EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); | ||
108 | |||
109 | int ieee802154_nl_disassoc_indic(struct net_device *dev, | ||
110 | struct ieee802154_addr *addr, u8 reason) | ||
111 | { | ||
112 | struct sk_buff *msg; | ||
113 | |||
114 | pr_debug("%s\n", __func__); | ||
115 | |||
116 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC); | ||
117 | if (!msg) | ||
118 | return -ENOBUFS; | ||
119 | |||
120 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
121 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
122 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
123 | dev->dev_addr); | ||
124 | |||
125 | if (addr->addr_type == IEEE802154_ADDR_LONG) | ||
126 | NLA_PUT(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | ||
127 | addr->hwaddr); | ||
128 | else | ||
129 | NLA_PUT_U16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, | ||
130 | addr->short_addr); | ||
131 | |||
132 | NLA_PUT_U8(msg, IEEE802154_ATTR_REASON, reason); | ||
133 | |||
134 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
135 | |||
136 | nla_put_failure: | ||
137 | nlmsg_free(msg); | ||
138 | return -ENOBUFS; | ||
139 | } | ||
140 | EXPORT_SYMBOL(ieee802154_nl_disassoc_indic); | ||
141 | |||
142 | int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status) | ||
143 | { | ||
144 | struct sk_buff *msg; | ||
145 | |||
146 | pr_debug("%s\n", __func__); | ||
147 | |||
148 | msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF); | ||
149 | if (!msg) | ||
150 | return -ENOBUFS; | ||
151 | |||
152 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
153 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
154 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
155 | dev->dev_addr); | ||
156 | |||
157 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
158 | |||
159 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
160 | |||
161 | nla_put_failure: | ||
162 | nlmsg_free(msg); | ||
163 | return -ENOBUFS; | ||
164 | } | ||
165 | EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); | ||
166 | |||
167 | int ieee802154_nl_beacon_indic(struct net_device *dev, | ||
168 | u16 panid, u16 coord_addr) | ||
169 | { | ||
170 | struct sk_buff *msg; | ||
171 | |||
172 | pr_debug("%s\n", __func__); | ||
173 | |||
174 | msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC); | ||
175 | if (!msg) | ||
176 | return -ENOBUFS; | ||
177 | |||
178 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
179 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
180 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
181 | dev->dev_addr); | ||
182 | NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr); | ||
183 | NLA_PUT_U16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid); | ||
184 | |||
185 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
186 | |||
187 | nla_put_failure: | ||
188 | nlmsg_free(msg); | ||
189 | return -ENOBUFS; | ||
190 | } | ||
191 | EXPORT_SYMBOL(ieee802154_nl_beacon_indic); | ||
192 | |||
193 | int ieee802154_nl_scan_confirm(struct net_device *dev, | ||
194 | u8 status, u8 scan_type, u32 unscanned, u8 page, | ||
195 | u8 *edl/* , struct list_head *pan_desc_list */) | ||
196 | { | ||
197 | struct sk_buff *msg; | ||
198 | |||
199 | pr_debug("%s\n", __func__); | ||
200 | |||
201 | msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF); | ||
202 | if (!msg) | ||
203 | return -ENOBUFS; | ||
204 | |||
205 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
206 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
207 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
208 | dev->dev_addr); | ||
209 | |||
210 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
211 | NLA_PUT_U8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type); | ||
212 | NLA_PUT_U32(msg, IEEE802154_ATTR_CHANNELS, unscanned); | ||
213 | NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, page); | ||
214 | |||
215 | if (edl) | ||
216 | NLA_PUT(msg, IEEE802154_ATTR_ED_LIST, 27, edl); | ||
217 | |||
218 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
219 | |||
220 | nla_put_failure: | ||
221 | nlmsg_free(msg); | ||
222 | return -ENOBUFS; | ||
223 | } | ||
224 | EXPORT_SYMBOL(ieee802154_nl_scan_confirm); | ||
225 | |||
226 | int ieee802154_nl_start_confirm(struct net_device *dev, u8 status) | ||
227 | { | ||
228 | struct sk_buff *msg; | ||
229 | |||
230 | pr_debug("%s\n", __func__); | ||
231 | |||
232 | msg = ieee802154_nl_create(0, IEEE802154_START_CONF); | ||
233 | if (!msg) | ||
234 | return -ENOBUFS; | ||
235 | |||
236 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
237 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
238 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
239 | dev->dev_addr); | ||
240 | |||
241 | NLA_PUT_U8(msg, IEEE802154_ATTR_STATUS, status); | ||
242 | |||
243 | return ieee802154_nl_mcast(msg, ieee802154_coord_mcgrp.id); | ||
244 | |||
245 | nla_put_failure: | ||
246 | nlmsg_free(msg); | ||
247 | return -ENOBUFS; | ||
248 | } | ||
249 | EXPORT_SYMBOL(ieee802154_nl_start_confirm); | ||
250 | |||
251 | static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 pid, | ||
252 | u32 seq, int flags, struct net_device *dev) | ||
253 | { | ||
254 | void *hdr; | ||
255 | struct wpan_phy *phy; | ||
256 | |||
257 | pr_debug("%s\n", __func__); | ||
258 | |||
259 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, | ||
260 | IEEE802154_LIST_IFACE); | ||
261 | if (!hdr) | ||
262 | goto out; | ||
263 | |||
264 | phy = ieee802154_mlme_ops(dev)->get_phy(dev); | ||
265 | BUG_ON(!phy); | ||
266 | |||
267 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
268 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); | ||
269 | NLA_PUT_U32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex); | ||
270 | |||
271 | NLA_PUT(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | ||
272 | dev->dev_addr); | ||
273 | NLA_PUT_U16(msg, IEEE802154_ATTR_SHORT_ADDR, | ||
274 | ieee802154_mlme_ops(dev)->get_short_addr(dev)); | ||
275 | NLA_PUT_U16(msg, IEEE802154_ATTR_PAN_ID, | ||
276 | ieee802154_mlme_ops(dev)->get_pan_id(dev)); | ||
277 | wpan_phy_put(phy); | ||
278 | return genlmsg_end(msg, hdr); | ||
279 | |||
280 | nla_put_failure: | ||
281 | wpan_phy_put(phy); | ||
282 | genlmsg_cancel(msg, hdr); | ||
283 | out: | ||
284 | return -EMSGSIZE; | ||
285 | } | ||
286 | |||
287 | /* Requests from userspace */ | ||
288 | static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) | ||
289 | { | ||
290 | struct net_device *dev; | ||
291 | |||
292 | if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { | ||
293 | char name[IFNAMSIZ + 1]; | ||
294 | nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], | ||
295 | sizeof(name)); | ||
296 | dev = dev_get_by_name(&init_net, name); | ||
297 | } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) | ||
298 | dev = dev_get_by_index(&init_net, | ||
299 | nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); | ||
300 | else | ||
301 | return NULL; | ||
302 | |||
303 | if (!dev) | ||
304 | return NULL; | ||
305 | |||
306 | if (dev->type != ARPHRD_IEEE802154) { | ||
307 | dev_put(dev); | ||
308 | return NULL; | ||
309 | } | ||
310 | |||
311 | return dev; | ||
312 | } | ||
313 | |||
314 | static int ieee802154_associate_req(struct sk_buff *skb, | ||
315 | struct genl_info *info) | ||
316 | { | ||
317 | struct net_device *dev; | ||
318 | struct ieee802154_addr addr; | ||
319 | u8 page; | ||
320 | int ret = -EINVAL; | ||
321 | |||
322 | if (!info->attrs[IEEE802154_ATTR_CHANNEL] || | ||
323 | !info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || | ||
324 | (!info->attrs[IEEE802154_ATTR_COORD_HW_ADDR] && | ||
325 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]) || | ||
326 | !info->attrs[IEEE802154_ATTR_CAPABILITY]) | ||
327 | return -EINVAL; | ||
328 | |||
329 | dev = ieee802154_nl_get_dev(info); | ||
330 | if (!dev) | ||
331 | return -ENODEV; | ||
332 | |||
333 | if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { | ||
334 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
335 | nla_memcpy(addr.hwaddr, | ||
336 | info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], | ||
337 | IEEE802154_ADDR_LEN); | ||
338 | } else { | ||
339 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
340 | addr.short_addr = nla_get_u16( | ||
341 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | ||
342 | } | ||
343 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
344 | |||
345 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
346 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
347 | else | ||
348 | page = 0; | ||
349 | |||
350 | ret = ieee802154_mlme_ops(dev)->assoc_req(dev, &addr, | ||
351 | nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]), | ||
352 | page, | ||
353 | nla_get_u8(info->attrs[IEEE802154_ATTR_CAPABILITY])); | ||
354 | |||
355 | dev_put(dev); | ||
356 | return ret; | ||
357 | } | ||
358 | |||
359 | static int ieee802154_associate_resp(struct sk_buff *skb, | ||
360 | struct genl_info *info) | ||
361 | { | ||
362 | struct net_device *dev; | ||
363 | struct ieee802154_addr addr; | ||
364 | int ret = -EINVAL; | ||
365 | |||
366 | if (!info->attrs[IEEE802154_ATTR_STATUS] || | ||
367 | !info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] || | ||
368 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) | ||
369 | return -EINVAL; | ||
370 | |||
371 | dev = ieee802154_nl_get_dev(info); | ||
372 | if (!dev) | ||
373 | return -ENODEV; | ||
374 | |||
375 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
376 | nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | ||
377 | IEEE802154_ADDR_LEN); | ||
378 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | ||
379 | |||
380 | |||
381 | ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, | ||
382 | nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), | ||
383 | nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); | ||
384 | |||
385 | dev_put(dev); | ||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | static int ieee802154_disassociate_req(struct sk_buff *skb, | ||
390 | struct genl_info *info) | ||
391 | { | ||
392 | struct net_device *dev; | ||
393 | struct ieee802154_addr addr; | ||
394 | int ret = -EINVAL; | ||
395 | |||
396 | if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && | ||
397 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || | ||
398 | !info->attrs[IEEE802154_ATTR_REASON]) | ||
399 | return -EINVAL; | ||
400 | |||
401 | dev = ieee802154_nl_get_dev(info); | ||
402 | if (!dev) | ||
403 | return -ENODEV; | ||
404 | |||
405 | if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { | ||
406 | addr.addr_type = IEEE802154_ADDR_LONG; | ||
407 | nla_memcpy(addr.hwaddr, | ||
408 | info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | ||
409 | IEEE802154_ADDR_LEN); | ||
410 | } else { | ||
411 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
412 | addr.short_addr = nla_get_u16( | ||
413 | info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); | ||
414 | } | ||
415 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | ||
416 | |||
417 | ret = ieee802154_mlme_ops(dev)->disassoc_req(dev, &addr, | ||
418 | nla_get_u8(info->attrs[IEEE802154_ATTR_REASON])); | ||
419 | |||
420 | dev_put(dev); | ||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | /* | ||
425 | * PANid, channel, beacon_order = 15, superframe_order = 15, | ||
426 | * PAN_coordinator, battery_life_extension = 0, | ||
427 | * coord_realignment = 0, security_enable = 0 | ||
428 | */ | ||
429 | static int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | ||
430 | { | ||
431 | struct net_device *dev; | ||
432 | struct ieee802154_addr addr; | ||
433 | |||
434 | u8 channel, bcn_ord, sf_ord; | ||
435 | u8 page; | ||
436 | int pan_coord, blx, coord_realign; | ||
437 | int ret; | ||
438 | |||
439 | if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] || | ||
440 | !info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] || | ||
441 | !info->attrs[IEEE802154_ATTR_CHANNEL] || | ||
442 | !info->attrs[IEEE802154_ATTR_BCN_ORD] || | ||
443 | !info->attrs[IEEE802154_ATTR_SF_ORD] || | ||
444 | !info->attrs[IEEE802154_ATTR_PAN_COORD] || | ||
445 | !info->attrs[IEEE802154_ATTR_BAT_EXT] || | ||
446 | !info->attrs[IEEE802154_ATTR_COORD_REALIGN] | ||
447 | ) | ||
448 | return -EINVAL; | ||
449 | |||
450 | dev = ieee802154_nl_get_dev(info); | ||
451 | if (!dev) | ||
452 | return -ENODEV; | ||
453 | |||
454 | addr.addr_type = IEEE802154_ADDR_SHORT; | ||
455 | addr.short_addr = nla_get_u16( | ||
456 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | ||
457 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
458 | |||
459 | channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); | ||
460 | bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); | ||
461 | sf_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_SF_ORD]); | ||
462 | pan_coord = nla_get_u8(info->attrs[IEEE802154_ATTR_PAN_COORD]); | ||
463 | blx = nla_get_u8(info->attrs[IEEE802154_ATTR_BAT_EXT]); | ||
464 | coord_realign = nla_get_u8(info->attrs[IEEE802154_ATTR_COORD_REALIGN]); | ||
465 | |||
466 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
467 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
468 | else | ||
469 | page = 0; | ||
470 | |||
471 | |||
472 | if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { | ||
473 | ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); | ||
474 | dev_put(dev); | ||
475 | return -EINVAL; | ||
476 | } | ||
477 | |||
478 | ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page, | ||
479 | bcn_ord, sf_ord, pan_coord, blx, coord_realign); | ||
480 | |||
481 | dev_put(dev); | ||
482 | return ret; | ||
483 | } | ||
484 | |||
485 | static int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) | ||
486 | { | ||
487 | struct net_device *dev; | ||
488 | int ret; | ||
489 | u8 type; | ||
490 | u32 channels; | ||
491 | u8 duration; | ||
492 | u8 page; | ||
493 | |||
494 | if (!info->attrs[IEEE802154_ATTR_SCAN_TYPE] || | ||
495 | !info->attrs[IEEE802154_ATTR_CHANNELS] || | ||
496 | !info->attrs[IEEE802154_ATTR_DURATION]) | ||
497 | return -EINVAL; | ||
498 | |||
499 | dev = ieee802154_nl_get_dev(info); | ||
500 | if (!dev) | ||
501 | return -ENODEV; | ||
502 | |||
503 | type = nla_get_u8(info->attrs[IEEE802154_ATTR_SCAN_TYPE]); | ||
504 | channels = nla_get_u32(info->attrs[IEEE802154_ATTR_CHANNELS]); | ||
505 | duration = nla_get_u8(info->attrs[IEEE802154_ATTR_DURATION]); | ||
506 | |||
507 | if (info->attrs[IEEE802154_ATTR_PAGE]) | ||
508 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | ||
509 | else | ||
510 | page = 0; | ||
511 | |||
512 | |||
513 | ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, | ||
514 | duration); | ||
515 | |||
516 | dev_put(dev); | ||
517 | return ret; | ||
518 | } | ||
519 | |||
520 | static int ieee802154_list_iface(struct sk_buff *skb, | ||
521 | struct genl_info *info) | ||
522 | { | ||
523 | /* Request for interface name, index, type, IEEE address, | ||
524 | PAN Id, short address */ | ||
525 | struct sk_buff *msg; | ||
526 | struct net_device *dev = NULL; | ||
527 | int rc = -ENOBUFS; | ||
528 | |||
529 | pr_debug("%s\n", __func__); | ||
530 | |||
531 | dev = ieee802154_nl_get_dev(info); | ||
532 | if (!dev) | ||
533 | return -ENODEV; | ||
534 | |||
535 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
536 | if (!msg) | ||
537 | goto out_dev; | ||
538 | |||
539 | rc = ieee802154_nl_fill_iface(msg, info->snd_pid, info->snd_seq, | ||
540 | 0, dev); | ||
541 | if (rc < 0) | ||
542 | goto out_free; | ||
543 | |||
544 | dev_put(dev); | ||
545 | |||
546 | return genlmsg_reply(msg, info); | ||
547 | out_free: | ||
548 | nlmsg_free(msg); | ||
549 | out_dev: | ||
550 | dev_put(dev); | ||
551 | return rc; | ||
552 | |||
553 | } | ||
554 | |||
555 | static int ieee802154_dump_iface(struct sk_buff *skb, | ||
556 | struct netlink_callback *cb) | ||
557 | { | ||
558 | struct net *net = sock_net(skb->sk); | ||
559 | struct net_device *dev; | ||
560 | int idx; | ||
561 | int s_idx = cb->args[0]; | ||
562 | |||
563 | pr_debug("%s\n", __func__); | ||
564 | |||
565 | idx = 0; | ||
566 | for_each_netdev(net, dev) { | ||
567 | if (idx < s_idx || (dev->type != ARPHRD_IEEE802154)) | ||
568 | goto cont; | ||
569 | |||
570 | if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).pid, | ||
571 | cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) | ||
572 | break; | ||
573 | cont: | ||
574 | idx++; | ||
575 | } | ||
576 | cb->args[0] = idx; | ||
577 | |||
578 | return skb->len; | ||
579 | } | ||
580 | |||
581 | static struct genl_ops ieee802154_coordinator_ops[] = { | ||
582 | IEEE802154_OP(IEEE802154_ASSOCIATE_REQ, ieee802154_associate_req), | ||
583 | IEEE802154_OP(IEEE802154_ASSOCIATE_RESP, ieee802154_associate_resp), | ||
584 | IEEE802154_OP(IEEE802154_DISASSOCIATE_REQ, ieee802154_disassociate_req), | ||
585 | IEEE802154_OP(IEEE802154_SCAN_REQ, ieee802154_scan_req), | ||
586 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), | ||
587 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, | ||
588 | ieee802154_dump_iface), | ||
589 | }; | ||
590 | |||
591 | /* | ||
592 | * No need to unregister as family unregistration will do it. | ||
593 | */ | ||
594 | int nl802154_mac_register(void) | ||
595 | { | ||
596 | int i; | ||
597 | int rc; | ||
598 | |||
599 | rc = genl_register_mc_group(&nl802154_family, | ||
600 | &ieee802154_coord_mcgrp); | ||
601 | if (rc) | ||
602 | return rc; | ||
603 | |||
604 | rc = genl_register_mc_group(&nl802154_family, | ||
605 | &ieee802154_beacon_mcgrp); | ||
606 | if (rc) | ||
607 | return rc; | ||
608 | |||
609 | for (i = 0; i < ARRAY_SIZE(ieee802154_coordinator_ops); i++) { | ||
610 | rc = genl_register_ops(&nl802154_family, | ||
611 | &ieee802154_coordinator_ops[i]); | ||
612 | if (rc) | ||
613 | return rc; | ||
614 | } | ||
615 | |||
616 | return 0; | ||
617 | } | ||
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c new file mode 100644 index 000000000000..199a2d9d12f9 --- /dev/null +++ b/net/ieee802154/nl-phy.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * Netlink inteface for IEEE 802.15.4 stack | ||
3 | * | ||
4 | * Copyright 2007, 2008 Siemens AG | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * Written by: | ||
20 | * Sergey Lapin <slapin@ossfans.org> | ||
21 | * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | ||
22 | * Maxim Osipov <maxim.osipov@siemens.com> | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <net/netlink.h> | ||
27 | #include <net/genetlink.h> | ||
28 | #include <net/wpan-phy.h> | ||
29 | #include <net/af_ieee802154.h> | ||
30 | #include <net/ieee802154_netdev.h> | ||
31 | #include <net/rtnetlink.h> /* for rtnl_{un,}lock */ | ||
32 | #include <linux/nl802154.h> | ||
33 | |||
34 | #include "ieee802154.h" | ||
35 | |||
36 | static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid, | ||
37 | u32 seq, int flags, struct wpan_phy *phy) | ||
38 | { | ||
39 | void *hdr; | ||
40 | int i, pages = 0; | ||
41 | uint32_t *buf = kzalloc(32 * sizeof(uint32_t), GFP_KERNEL); | ||
42 | |||
43 | pr_debug("%s\n", __func__); | ||
44 | |||
45 | if (!buf) | ||
46 | goto out; | ||
47 | |||
48 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, | ||
49 | IEEE802154_LIST_PHY); | ||
50 | if (!hdr) | ||
51 | goto out; | ||
52 | |||
53 | mutex_lock(&phy->pib_lock); | ||
54 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); | ||
55 | |||
56 | NLA_PUT_U8(msg, IEEE802154_ATTR_PAGE, phy->current_page); | ||
57 | NLA_PUT_U8(msg, IEEE802154_ATTR_CHANNEL, phy->current_channel); | ||
58 | for (i = 0; i < 32; i++) { | ||
59 | if (phy->channels_supported[i]) | ||
60 | buf[pages++] = phy->channels_supported[i] | (i << 27); | ||
61 | } | ||
62 | if (pages) | ||
63 | NLA_PUT(msg, IEEE802154_ATTR_CHANNEL_PAGE_LIST, | ||
64 | pages * sizeof(uint32_t), buf); | ||
65 | |||
66 | mutex_unlock(&phy->pib_lock); | ||
67 | return genlmsg_end(msg, hdr); | ||
68 | |||
69 | nla_put_failure: | ||
70 | mutex_unlock(&phy->pib_lock); | ||
71 | genlmsg_cancel(msg, hdr); | ||
72 | out: | ||
73 | kfree(buf); | ||
74 | return -EMSGSIZE; | ||
75 | } | ||
76 | |||
77 | static int ieee802154_list_phy(struct sk_buff *skb, | ||
78 | struct genl_info *info) | ||
79 | { | ||
80 | /* Request for interface name, index, type, IEEE address, | ||
81 | PAN Id, short address */ | ||
82 | struct sk_buff *msg; | ||
83 | struct wpan_phy *phy; | ||
84 | const char *name; | ||
85 | int rc = -ENOBUFS; | ||
86 | |||
87 | pr_debug("%s\n", __func__); | ||
88 | |||
89 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME]) | ||
90 | return -EINVAL; | ||
91 | |||
92 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | ||
93 | if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0') | ||
94 | return -EINVAL; /* phy name should be null-terminated */ | ||
95 | |||
96 | |||
97 | phy = wpan_phy_find(name); | ||
98 | if (!phy) | ||
99 | return -ENODEV; | ||
100 | |||
101 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
102 | if (!msg) | ||
103 | goto out_dev; | ||
104 | |||
105 | rc = ieee802154_nl_fill_phy(msg, info->snd_pid, info->snd_seq, | ||
106 | 0, phy); | ||
107 | if (rc < 0) | ||
108 | goto out_free; | ||
109 | |||
110 | wpan_phy_put(phy); | ||
111 | |||
112 | return genlmsg_reply(msg, info); | ||
113 | out_free: | ||
114 | nlmsg_free(msg); | ||
115 | out_dev: | ||
116 | wpan_phy_put(phy); | ||
117 | return rc; | ||
118 | |||
119 | } | ||
120 | |||
121 | struct dump_phy_data { | ||
122 | struct sk_buff *skb; | ||
123 | struct netlink_callback *cb; | ||
124 | int idx, s_idx; | ||
125 | }; | ||
126 | |||
127 | static int ieee802154_dump_phy_iter(struct wpan_phy *phy, void *_data) | ||
128 | { | ||
129 | int rc; | ||
130 | struct dump_phy_data *data = _data; | ||
131 | |||
132 | pr_debug("%s\n", __func__); | ||
133 | |||
134 | if (data->idx++ < data->s_idx) | ||
135 | return 0; | ||
136 | |||
137 | rc = ieee802154_nl_fill_phy(data->skb, | ||
138 | NETLINK_CB(data->cb->skb).pid, | ||
139 | data->cb->nlh->nlmsg_seq, | ||
140 | NLM_F_MULTI, | ||
141 | phy); | ||
142 | |||
143 | if (rc < 0) { | ||
144 | data->idx--; | ||
145 | return rc; | ||
146 | } | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int ieee802154_dump_phy(struct sk_buff *skb, | ||
152 | struct netlink_callback *cb) | ||
153 | { | ||
154 | struct dump_phy_data data = { | ||
155 | .cb = cb, | ||
156 | .skb = skb, | ||
157 | .s_idx = cb->args[0], | ||
158 | .idx = 0, | ||
159 | }; | ||
160 | |||
161 | pr_debug("%s\n", __func__); | ||
162 | |||
163 | wpan_phy_for_each(ieee802154_dump_phy_iter, &data); | ||
164 | |||
165 | cb->args[0] = data.idx; | ||
166 | |||
167 | return skb->len; | ||
168 | } | ||
169 | |||
170 | static int ieee802154_add_iface(struct sk_buff *skb, | ||
171 | struct genl_info *info) | ||
172 | { | ||
173 | struct sk_buff *msg; | ||
174 | struct wpan_phy *phy; | ||
175 | const char *name; | ||
176 | const char *devname; | ||
177 | int rc = -ENOBUFS; | ||
178 | struct net_device *dev; | ||
179 | |||
180 | pr_debug("%s\n", __func__); | ||
181 | |||
182 | if (!info->attrs[IEEE802154_ATTR_PHY_NAME]) | ||
183 | return -EINVAL; | ||
184 | |||
185 | name = nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | ||
186 | if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0') | ||
187 | return -EINVAL; /* phy name should be null-terminated */ | ||
188 | |||
189 | if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { | ||
190 | devname = nla_data(info->attrs[IEEE802154_ATTR_DEV_NAME]); | ||
191 | if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] | ||
192 | != '\0') | ||
193 | return -EINVAL; /* phy name should be null-terminated */ | ||
194 | } else { | ||
195 | devname = "wpan%d"; | ||
196 | } | ||
197 | |||
198 | if (strlen(devname) >= IFNAMSIZ) | ||
199 | return -ENAMETOOLONG; | ||
200 | |||
201 | phy = wpan_phy_find(name); | ||
202 | if (!phy) | ||
203 | return -ENODEV; | ||
204 | |||
205 | msg = ieee802154_nl_new_reply(info, 0, IEEE802154_ADD_IFACE); | ||
206 | if (!msg) | ||
207 | goto out_dev; | ||
208 | |||
209 | if (!phy->add_iface) { | ||
210 | rc = -EINVAL; | ||
211 | goto nla_put_failure; | ||
212 | } | ||
213 | |||
214 | dev = phy->add_iface(phy, devname); | ||
215 | if (IS_ERR(dev)) { | ||
216 | rc = PTR_ERR(dev); | ||
217 | goto nla_put_failure; | ||
218 | } | ||
219 | |||
220 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); | ||
221 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, dev->name); | ||
222 | |||
223 | dev_put(dev); | ||
224 | |||
225 | wpan_phy_put(phy); | ||
226 | |||
227 | return ieee802154_nl_reply(msg, info); | ||
228 | |||
229 | nla_put_failure: | ||
230 | nlmsg_free(msg); | ||
231 | out_dev: | ||
232 | wpan_phy_put(phy); | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | static int ieee802154_del_iface(struct sk_buff *skb, | ||
237 | struct genl_info *info) | ||
238 | { | ||
239 | struct sk_buff *msg; | ||
240 | struct wpan_phy *phy; | ||
241 | const char *name; | ||
242 | int rc; | ||
243 | struct net_device *dev; | ||
244 | |||
245 | pr_debug("%s\n", __func__); | ||
246 | |||
247 | if (!info->attrs[IEEE802154_ATTR_DEV_NAME]) | ||
248 | return -EINVAL; | ||
249 | |||
250 | name = nla_data(info->attrs[IEEE802154_ATTR_DEV_NAME]); | ||
251 | if (name[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1] != '\0') | ||
252 | return -EINVAL; /* name should be null-terminated */ | ||
253 | |||
254 | dev = dev_get_by_name(genl_info_net(info), name); | ||
255 | if (!dev) | ||
256 | return -ENODEV; | ||
257 | |||
258 | phy = ieee802154_mlme_ops(dev)->get_phy(dev); | ||
259 | BUG_ON(!phy); | ||
260 | |||
261 | rc = -EINVAL; | ||
262 | /* phy name is optional, but should be checked if it's given */ | ||
263 | if (info->attrs[IEEE802154_ATTR_PHY_NAME]) { | ||
264 | struct wpan_phy *phy2; | ||
265 | |||
266 | const char *pname = | ||
267 | nla_data(info->attrs[IEEE802154_ATTR_PHY_NAME]); | ||
268 | if (pname[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] | ||
269 | != '\0') | ||
270 | /* name should be null-terminated */ | ||
271 | goto out_dev; | ||
272 | |||
273 | phy2 = wpan_phy_find(pname); | ||
274 | if (!phy2) | ||
275 | goto out_dev; | ||
276 | |||
277 | if (phy != phy2) { | ||
278 | wpan_phy_put(phy2); | ||
279 | goto out_dev; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | rc = -ENOBUFS; | ||
284 | |||
285 | msg = ieee802154_nl_new_reply(info, 0, IEEE802154_DEL_IFACE); | ||
286 | if (!msg) | ||
287 | goto out_dev; | ||
288 | |||
289 | if (!phy->del_iface) { | ||
290 | rc = -EINVAL; | ||
291 | goto nla_put_failure; | ||
292 | } | ||
293 | |||
294 | rtnl_lock(); | ||
295 | phy->del_iface(phy, dev); | ||
296 | |||
297 | /* We don't have device anymore */ | ||
298 | dev_put(dev); | ||
299 | dev = NULL; | ||
300 | |||
301 | rtnl_unlock(); | ||
302 | |||
303 | |||
304 | NLA_PUT_STRING(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)); | ||
305 | NLA_PUT_STRING(msg, IEEE802154_ATTR_DEV_NAME, name); | ||
306 | |||
307 | wpan_phy_put(phy); | ||
308 | |||
309 | return ieee802154_nl_reply(msg, info); | ||
310 | |||
311 | nla_put_failure: | ||
312 | nlmsg_free(msg); | ||
313 | out_dev: | ||
314 | wpan_phy_put(phy); | ||
315 | if (dev) | ||
316 | dev_put(dev); | ||
317 | |||
318 | return rc; | ||
319 | } | ||
320 | |||
321 | static struct genl_ops ieee802154_phy_ops[] = { | ||
322 | IEEE802154_DUMP(IEEE802154_LIST_PHY, ieee802154_list_phy, | ||
323 | ieee802154_dump_phy), | ||
324 | IEEE802154_OP(IEEE802154_ADD_IFACE, ieee802154_add_iface), | ||
325 | IEEE802154_OP(IEEE802154_DEL_IFACE, ieee802154_del_iface), | ||
326 | }; | ||
327 | |||
328 | /* | ||
329 | * No need to unregister as family unregistration will do it. | ||
330 | */ | ||
331 | int nl802154_phy_register(void) | ||
332 | { | ||
333 | int i; | ||
334 | int rc; | ||
335 | |||
336 | for (i = 0; i < ARRAY_SIZE(ieee802154_phy_ops); i++) { | ||
337 | rc = genl_register_ops(&nl802154_family, | ||
338 | &ieee802154_phy_ops[i]); | ||
339 | if (rc) | ||
340 | return rc; | ||
341 | } | ||
342 | |||
343 | return 0; | ||
344 | } | ||
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 2363ebee02e7..6adda4d46f95 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c | |||
@@ -27,6 +27,7 @@ | |||
27 | const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { | 27 | const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { |
28 | [IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, }, | 28 | [IEEE802154_ATTR_DEV_NAME] = { .type = NLA_STRING, }, |
29 | [IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, }, | 29 | [IEEE802154_ATTR_DEV_INDEX] = { .type = NLA_U32, }, |
30 | [IEEE802154_ATTR_PHY_NAME] = { .type = NLA_STRING, }, | ||
30 | 31 | ||
31 | [IEEE802154_ATTR_STATUS] = { .type = NLA_U8, }, | 32 | [IEEE802154_ATTR_STATUS] = { .type = NLA_U8, }, |
32 | [IEEE802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, | 33 | [IEEE802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, }, |
@@ -50,5 +51,6 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { | |||
50 | [IEEE802154_ATTR_CHANNELS] = { .type = NLA_U32, }, | 51 | [IEEE802154_ATTR_CHANNELS] = { .type = NLA_U32, }, |
51 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, | 52 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, |
52 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, | 53 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, |
54 | [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, | ||
53 | }; | 55 | }; |
54 | 56 | ||
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index f306604da67a..38bac70cca10 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include <net/wpan-phy.h> | 23 | #include <net/wpan-phy.h> |
24 | 24 | ||
25 | #include "ieee802154.h" | ||
26 | |||
25 | #define MASTER_SHOW_COMPLEX(name, format_string, args...) \ | 27 | #define MASTER_SHOW_COMPLEX(name, format_string, args...) \ |
26 | static ssize_t name ## _show(struct device *dev, \ | 28 | static ssize_t name ## _show(struct device *dev, \ |
27 | struct device_attribute *attr, char *buf) \ | 29 | struct device_attribute *attr, char *buf) \ |
@@ -30,7 +32,7 @@ static ssize_t name ## _show(struct device *dev, \ | |||
30 | int ret; \ | 32 | int ret; \ |
31 | \ | 33 | \ |
32 | mutex_lock(&phy->pib_lock); \ | 34 | mutex_lock(&phy->pib_lock); \ |
33 | ret = sprintf(buf, format_string "\n", args); \ | 35 | ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \ |
34 | mutex_unlock(&phy->pib_lock); \ | 36 | mutex_unlock(&phy->pib_lock); \ |
35 | return ret; \ | 37 | return ret; \ |
36 | } | 38 | } |
@@ -40,12 +42,30 @@ static ssize_t name ## _show(struct device *dev, \ | |||
40 | 42 | ||
41 | MASTER_SHOW(current_channel, "%d"); | 43 | MASTER_SHOW(current_channel, "%d"); |
42 | MASTER_SHOW(current_page, "%d"); | 44 | MASTER_SHOW(current_page, "%d"); |
43 | MASTER_SHOW(channels_supported, "%#x"); | ||
44 | MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB", | 45 | MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB", |
45 | ((signed char) (phy->transmit_power << 2)) >> 2, | 46 | ((signed char) (phy->transmit_power << 2)) >> 2, |
46 | (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1 ); | 47 | (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1 ); |
47 | MASTER_SHOW(cca_mode, "%d"); | 48 | MASTER_SHOW(cca_mode, "%d"); |
48 | 49 | ||
50 | static ssize_t channels_supported_show(struct device *dev, | ||
51 | struct device_attribute *attr, char *buf) | ||
52 | { | ||
53 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); | ||
54 | int ret; | ||
55 | int i, len = 0; | ||
56 | |||
57 | mutex_lock(&phy->pib_lock); | ||
58 | for (i = 0; i < 32; i++) { | ||
59 | ret = snprintf(buf + len, PAGE_SIZE - len, | ||
60 | "%#09x\n", phy->channels_supported[i]); | ||
61 | if (ret < 0) | ||
62 | break; | ||
63 | len += ret; | ||
64 | } | ||
65 | mutex_unlock(&phy->pib_lock); | ||
66 | return len; | ||
67 | } | ||
68 | |||
49 | static struct device_attribute pmib_attrs[] = { | 69 | static struct device_attribute pmib_attrs[] = { |
50 | __ATTR_RO(current_channel), | 70 | __ATTR_RO(current_channel), |
51 | __ATTR_RO(current_page), | 71 | __ATTR_RO(current_page), |
@@ -91,6 +111,31 @@ struct wpan_phy *wpan_phy_find(const char *str) | |||
91 | } | 111 | } |
92 | EXPORT_SYMBOL(wpan_phy_find); | 112 | EXPORT_SYMBOL(wpan_phy_find); |
93 | 113 | ||
114 | struct wpan_phy_iter_data { | ||
115 | int (*fn)(struct wpan_phy *phy, void *data); | ||
116 | void *data; | ||
117 | }; | ||
118 | |||
119 | static int wpan_phy_iter(struct device *dev, void *_data) | ||
120 | { | ||
121 | struct wpan_phy_iter_data *wpid = _data; | ||
122 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); | ||
123 | return wpid->fn(phy, wpid->data); | ||
124 | } | ||
125 | |||
126 | int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), | ||
127 | void *data) | ||
128 | { | ||
129 | struct wpan_phy_iter_data wpid = { | ||
130 | .fn = fn, | ||
131 | .data = data, | ||
132 | }; | ||
133 | |||
134 | return class_for_each_device(&wpan_phy_class, NULL, | ||
135 | &wpid, wpan_phy_iter); | ||
136 | } | ||
137 | EXPORT_SYMBOL(wpan_phy_for_each); | ||
138 | |||
94 | static int wpan_phy_idx_valid(int idx) | 139 | static int wpan_phy_idx_valid(int idx) |
95 | { | 140 | { |
96 | return idx >= 0; | 141 | return idx >= 0; |
@@ -118,14 +163,15 @@ struct wpan_phy *wpan_phy_alloc(size_t priv_size) | |||
118 | 163 | ||
119 | phy->dev.class = &wpan_phy_class; | 164 | phy->dev.class = &wpan_phy_class; |
120 | 165 | ||
166 | phy->current_channel = -1; /* not initialised */ | ||
167 | phy->current_page = 0; /* for compatibility */ | ||
168 | |||
121 | return phy; | 169 | return phy; |
122 | } | 170 | } |
123 | EXPORT_SYMBOL(wpan_phy_alloc); | 171 | EXPORT_SYMBOL(wpan_phy_alloc); |
124 | 172 | ||
125 | int wpan_phy_register(struct device *parent, struct wpan_phy *phy) | 173 | int wpan_phy_register(struct wpan_phy *phy) |
126 | { | 174 | { |
127 | phy->dev.parent = parent; | ||
128 | |||
129 | return device_add(&phy->dev); | 175 | return device_add(&phy->dev); |
130 | } | 176 | } |
131 | EXPORT_SYMBOL(wpan_phy_register); | 177 | EXPORT_SYMBOL(wpan_phy_register); |
@@ -144,16 +190,31 @@ EXPORT_SYMBOL(wpan_phy_free); | |||
144 | 190 | ||
145 | static int __init wpan_phy_class_init(void) | 191 | static int __init wpan_phy_class_init(void) |
146 | { | 192 | { |
147 | return class_register(&wpan_phy_class); | 193 | int rc; |
194 | rc = class_register(&wpan_phy_class); | ||
195 | if (rc) | ||
196 | goto err; | ||
197 | |||
198 | rc = ieee802154_nl_init(); | ||
199 | if (rc) | ||
200 | goto err_nl; | ||
201 | |||
202 | return 0; | ||
203 | err_nl: | ||
204 | class_unregister(&wpan_phy_class); | ||
205 | err: | ||
206 | return rc; | ||
148 | } | 207 | } |
149 | subsys_initcall(wpan_phy_class_init); | 208 | module_init(wpan_phy_class_init); |
150 | 209 | ||
151 | static void __exit wpan_phy_class_exit(void) | 210 | static void __exit wpan_phy_class_exit(void) |
152 | { | 211 | { |
212 | ieee802154_nl_exit(); | ||
153 | class_unregister(&wpan_phy_class); | 213 | class_unregister(&wpan_phy_class); |
154 | } | 214 | } |
155 | module_exit(wpan_phy_class_exit); | 215 | module_exit(wpan_phy_class_exit); |
156 | 216 | ||
157 | MODULE_DESCRIPTION("IEEE 802.15.4 device class"); | ||
158 | MODULE_LICENSE("GPL v2"); | 217 | MODULE_LICENSE("GPL v2"); |
218 | MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface"); | ||
219 | MODULE_AUTHOR("Dmitry Eremin-Solenikov"); | ||
159 | 220 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 538e84d0bcba..7d12c6a9b19b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -262,7 +262,8 @@ static inline int inet_netns_ok(struct net *net, int protocol) | |||
262 | * Create an inet socket. | 262 | * Create an inet socket. |
263 | */ | 263 | */ |
264 | 264 | ||
265 | static int inet_create(struct net *net, struct socket *sock, int protocol) | 265 | static int inet_create(struct net *net, struct socket *sock, int protocol, |
266 | int kern) | ||
266 | { | 267 | { |
267 | struct sock *sk; | 268 | struct sock *sk; |
268 | struct inet_protosw *answer; | 269 | struct inet_protosw *answer; |
@@ -325,7 +326,7 @@ lookup_protocol: | |||
325 | } | 326 | } |
326 | 327 | ||
327 | err = -EPERM; | 328 | err = -EPERM; |
328 | if (answer->capability > 0 && !capable(answer->capability)) | 329 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
329 | goto out_rcu_unlock; | 330 | goto out_rcu_unlock; |
330 | 331 | ||
331 | err = -EAFNOSUPPORT; | 332 | err = -EAFNOSUPPORT; |
@@ -947,7 +948,6 @@ static struct inet_protosw inetsw_array[] = | |||
947 | .protocol = IPPROTO_TCP, | 948 | .protocol = IPPROTO_TCP, |
948 | .prot = &tcp_prot, | 949 | .prot = &tcp_prot, |
949 | .ops = &inet_stream_ops, | 950 | .ops = &inet_stream_ops, |
950 | .capability = -1, | ||
951 | .no_check = 0, | 951 | .no_check = 0, |
952 | .flags = INET_PROTOSW_PERMANENT | | 952 | .flags = INET_PROTOSW_PERMANENT | |
953 | INET_PROTOSW_ICSK, | 953 | INET_PROTOSW_ICSK, |
@@ -958,7 +958,6 @@ static struct inet_protosw inetsw_array[] = | |||
958 | .protocol = IPPROTO_UDP, | 958 | .protocol = IPPROTO_UDP, |
959 | .prot = &udp_prot, | 959 | .prot = &udp_prot, |
960 | .ops = &inet_dgram_ops, | 960 | .ops = &inet_dgram_ops, |
961 | .capability = -1, | ||
962 | .no_check = UDP_CSUM_DEFAULT, | 961 | .no_check = UDP_CSUM_DEFAULT, |
963 | .flags = INET_PROTOSW_PERMANENT, | 962 | .flags = INET_PROTOSW_PERMANENT, |
964 | }, | 963 | }, |
@@ -969,7 +968,6 @@ static struct inet_protosw inetsw_array[] = | |||
969 | .protocol = IPPROTO_IP, /* wild card */ | 968 | .protocol = IPPROTO_IP, /* wild card */ |
970 | .prot = &raw_prot, | 969 | .prot = &raw_prot, |
971 | .ops = &inet_sockraw_ops, | 970 | .ops = &inet_sockraw_ops, |
972 | .capability = CAP_NET_RAW, | ||
973 | .no_check = UDP_CSUM_DEFAULT, | 971 | .no_check = UDP_CSUM_DEFAULT, |
974 | .flags = INET_PROTOSW_REUSE, | 972 | .flags = INET_PROTOSW_REUSE, |
975 | } | 973 | } |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5df2f6a0b0f0..c2045f9615da 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -140,11 +140,11 @@ void in_dev_finish_destroy(struct in_device *idev) | |||
140 | #endif | 140 | #endif |
141 | dev_put(dev); | 141 | dev_put(dev); |
142 | if (!idev->dead) | 142 | if (!idev->dead) |
143 | printk("Freeing alive in_device %p\n", idev); | 143 | pr_err("Freeing alive in_device %p\n", idev); |
144 | else { | 144 | else |
145 | kfree(idev); | 145 | kfree(idev); |
146 | } | ||
147 | } | 146 | } |
147 | EXPORT_SYMBOL(in_dev_finish_destroy); | ||
148 | 148 | ||
149 | static struct in_device *inetdev_init(struct net_device *dev) | 149 | static struct in_device *inetdev_init(struct net_device *dev) |
150 | { | 150 | { |
@@ -159,7 +159,8 @@ static struct in_device *inetdev_init(struct net_device *dev) | |||
159 | sizeof(in_dev->cnf)); | 159 | sizeof(in_dev->cnf)); |
160 | in_dev->cnf.sysctl = NULL; | 160 | in_dev->cnf.sysctl = NULL; |
161 | in_dev->dev = dev; | 161 | in_dev->dev = dev; |
162 | if ((in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl)) == NULL) | 162 | in_dev->arp_parms = neigh_parms_alloc(dev, &arp_tbl); |
163 | if (!in_dev->arp_parms) | ||
163 | goto out_kfree; | 164 | goto out_kfree; |
164 | if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) | 165 | if (IPV4_DEVCONF(in_dev->cnf, FORWARDING)) |
165 | dev_disable_lro(dev); | 166 | dev_disable_lro(dev); |
@@ -405,13 +406,15 @@ struct in_device *inetdev_by_index(struct net *net, int ifindex) | |||
405 | { | 406 | { |
406 | struct net_device *dev; | 407 | struct net_device *dev; |
407 | struct in_device *in_dev = NULL; | 408 | struct in_device *in_dev = NULL; |
408 | read_lock(&dev_base_lock); | 409 | |
409 | dev = __dev_get_by_index(net, ifindex); | 410 | rcu_read_lock(); |
411 | dev = dev_get_by_index_rcu(net, ifindex); | ||
410 | if (dev) | 412 | if (dev) |
411 | in_dev = in_dev_get(dev); | 413 | in_dev = in_dev_get(dev); |
412 | read_unlock(&dev_base_lock); | 414 | rcu_read_unlock(); |
413 | return in_dev; | 415 | return in_dev; |
414 | } | 416 | } |
417 | EXPORT_SYMBOL(inetdev_by_index); | ||
415 | 418 | ||
416 | /* Called only from RTNL semaphored context. No locks. */ | 419 | /* Called only from RTNL semaphored context. No locks. */ |
417 | 420 | ||
@@ -557,7 +560,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg | |||
557 | * Determine a default network mask, based on the IP address. | 560 | * Determine a default network mask, based on the IP address. |
558 | */ | 561 | */ |
559 | 562 | ||
560 | static __inline__ int inet_abc_len(__be32 addr) | 563 | static inline int inet_abc_len(__be32 addr) |
561 | { | 564 | { |
562 | int rc = -1; /* Something else, probably a multicast. */ | 565 | int rc = -1; /* Something else, probably a multicast. */ |
563 | 566 | ||
@@ -646,13 +649,15 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
646 | rtnl_lock(); | 649 | rtnl_lock(); |
647 | 650 | ||
648 | ret = -ENODEV; | 651 | ret = -ENODEV; |
649 | if ((dev = __dev_get_by_name(net, ifr.ifr_name)) == NULL) | 652 | dev = __dev_get_by_name(net, ifr.ifr_name); |
653 | if (!dev) | ||
650 | goto done; | 654 | goto done; |
651 | 655 | ||
652 | if (colon) | 656 | if (colon) |
653 | *colon = ':'; | 657 | *colon = ':'; |
654 | 658 | ||
655 | if ((in_dev = __in_dev_get_rtnl(dev)) != NULL) { | 659 | in_dev = __in_dev_get_rtnl(dev); |
660 | if (in_dev) { | ||
656 | if (tryaddrmatch) { | 661 | if (tryaddrmatch) { |
657 | /* Matthias Andree */ | 662 | /* Matthias Andree */ |
658 | /* compare label and address (4.4BSD style) */ | 663 | /* compare label and address (4.4BSD style) */ |
@@ -720,7 +725,8 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
720 | 725 | ||
721 | if (!ifa) { | 726 | if (!ifa) { |
722 | ret = -ENOBUFS; | 727 | ret = -ENOBUFS; |
723 | if ((ifa = inet_alloc_ifa()) == NULL) | 728 | ifa = inet_alloc_ifa(); |
729 | if (!ifa) | ||
724 | break; | 730 | break; |
725 | if (colon) | 731 | if (colon) |
726 | memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); | 732 | memcpy(ifa->ifa_label, ifr.ifr_name, IFNAMSIZ); |
@@ -822,10 +828,10 @@ static int inet_gifconf(struct net_device *dev, char __user *buf, int len) | |||
822 | struct ifreq ifr; | 828 | struct ifreq ifr; |
823 | int done = 0; | 829 | int done = 0; |
824 | 830 | ||
825 | if (!in_dev || (ifa = in_dev->ifa_list) == NULL) | 831 | if (!in_dev) |
826 | goto out; | 832 | goto out; |
827 | 833 | ||
828 | for (; ifa; ifa = ifa->ifa_next) { | 834 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { |
829 | if (!buf) { | 835 | if (!buf) { |
830 | done += sizeof(ifr); | 836 | done += sizeof(ifr); |
831 | continue; | 837 | continue; |
@@ -875,36 +881,33 @@ __be32 inet_select_addr(const struct net_device *dev, __be32 dst, int scope) | |||
875 | if (!addr) | 881 | if (!addr) |
876 | addr = ifa->ifa_local; | 882 | addr = ifa->ifa_local; |
877 | } endfor_ifa(in_dev); | 883 | } endfor_ifa(in_dev); |
878 | no_in_dev: | ||
879 | rcu_read_unlock(); | ||
880 | 884 | ||
881 | if (addr) | 885 | if (addr) |
882 | goto out; | 886 | goto out_unlock; |
887 | no_in_dev: | ||
883 | 888 | ||
884 | /* Not loopback addresses on loopback should be preferred | 889 | /* Not loopback addresses on loopback should be preferred |
885 | in this case. It is importnat that lo is the first interface | 890 | in this case. It is importnat that lo is the first interface |
886 | in dev_base list. | 891 | in dev_base list. |
887 | */ | 892 | */ |
888 | read_lock(&dev_base_lock); | 893 | for_each_netdev_rcu(net, dev) { |
889 | rcu_read_lock(); | 894 | in_dev = __in_dev_get_rcu(dev); |
890 | for_each_netdev(net, dev) { | 895 | if (!in_dev) |
891 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL) | ||
892 | continue; | 896 | continue; |
893 | 897 | ||
894 | for_primary_ifa(in_dev) { | 898 | for_primary_ifa(in_dev) { |
895 | if (ifa->ifa_scope != RT_SCOPE_LINK && | 899 | if (ifa->ifa_scope != RT_SCOPE_LINK && |
896 | ifa->ifa_scope <= scope) { | 900 | ifa->ifa_scope <= scope) { |
897 | addr = ifa->ifa_local; | 901 | addr = ifa->ifa_local; |
898 | goto out_unlock_both; | 902 | goto out_unlock; |
899 | } | 903 | } |
900 | } endfor_ifa(in_dev); | 904 | } endfor_ifa(in_dev); |
901 | } | 905 | } |
902 | out_unlock_both: | 906 | out_unlock: |
903 | read_unlock(&dev_base_lock); | ||
904 | rcu_read_unlock(); | 907 | rcu_read_unlock(); |
905 | out: | ||
906 | return addr; | 908 | return addr; |
907 | } | 909 | } |
910 | EXPORT_SYMBOL(inet_select_addr); | ||
908 | 911 | ||
909 | static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | 912 | static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, |
910 | __be32 local, int scope) | 913 | __be32 local, int scope) |
@@ -940,7 +943,7 @@ static __be32 confirm_addr_indev(struct in_device *in_dev, __be32 dst, | |||
940 | } | 943 | } |
941 | } endfor_ifa(in_dev); | 944 | } endfor_ifa(in_dev); |
942 | 945 | ||
943 | return same? addr : 0; | 946 | return same ? addr : 0; |
944 | } | 947 | } |
945 | 948 | ||
946 | /* | 949 | /* |
@@ -961,17 +964,16 @@ __be32 inet_confirm_addr(struct in_device *in_dev, | |||
961 | return confirm_addr_indev(in_dev, dst, local, scope); | 964 | return confirm_addr_indev(in_dev, dst, local, scope); |
962 | 965 | ||
963 | net = dev_net(in_dev->dev); | 966 | net = dev_net(in_dev->dev); |
964 | read_lock(&dev_base_lock); | ||
965 | rcu_read_lock(); | 967 | rcu_read_lock(); |
966 | for_each_netdev(net, dev) { | 968 | for_each_netdev_rcu(net, dev) { |
967 | if ((in_dev = __in_dev_get_rcu(dev))) { | 969 | in_dev = __in_dev_get_rcu(dev); |
970 | if (in_dev) { | ||
968 | addr = confirm_addr_indev(in_dev, dst, local, scope); | 971 | addr = confirm_addr_indev(in_dev, dst, local, scope); |
969 | if (addr) | 972 | if (addr) |
970 | break; | 973 | break; |
971 | } | 974 | } |
972 | } | 975 | } |
973 | rcu_read_unlock(); | 976 | rcu_read_unlock(); |
974 | read_unlock(&dev_base_lock); | ||
975 | 977 | ||
976 | return addr; | 978 | return addr; |
977 | } | 979 | } |
@@ -984,14 +986,16 @@ int register_inetaddr_notifier(struct notifier_block *nb) | |||
984 | { | 986 | { |
985 | return blocking_notifier_chain_register(&inetaddr_chain, nb); | 987 | return blocking_notifier_chain_register(&inetaddr_chain, nb); |
986 | } | 988 | } |
989 | EXPORT_SYMBOL(register_inetaddr_notifier); | ||
987 | 990 | ||
988 | int unregister_inetaddr_notifier(struct notifier_block *nb) | 991 | int unregister_inetaddr_notifier(struct notifier_block *nb) |
989 | { | 992 | { |
990 | return blocking_notifier_chain_unregister(&inetaddr_chain, nb); | 993 | return blocking_notifier_chain_unregister(&inetaddr_chain, nb); |
991 | } | 994 | } |
995 | EXPORT_SYMBOL(unregister_inetaddr_notifier); | ||
992 | 996 | ||
993 | /* Rename ifa_labels for a device name change. Make some effort to preserve existing | 997 | /* Rename ifa_labels for a device name change. Make some effort to preserve |
994 | * alias numbering and to create unique labels if possible. | 998 | * existing alias numbering and to create unique labels if possible. |
995 | */ | 999 | */ |
996 | static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | 1000 | static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) |
997 | { | 1001 | { |
@@ -1010,11 +1014,10 @@ static void inetdev_changename(struct net_device *dev, struct in_device *in_dev) | |||
1010 | sprintf(old, ":%d", named); | 1014 | sprintf(old, ":%d", named); |
1011 | dot = old; | 1015 | dot = old; |
1012 | } | 1016 | } |
1013 | if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) { | 1017 | if (strlen(dot) + strlen(dev->name) < IFNAMSIZ) |
1014 | strcat(ifa->ifa_label, dot); | 1018 | strcat(ifa->ifa_label, dot); |
1015 | } else { | 1019 | else |
1016 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); | 1020 | strcpy(ifa->ifa_label + (IFNAMSIZ - strlen(dot) - 1), dot); |
1017 | } | ||
1018 | skip: | 1021 | skip: |
1019 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); | 1022 | rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0); |
1020 | } | 1023 | } |
@@ -1061,8 +1064,9 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1061 | if (!inetdev_valid_mtu(dev->mtu)) | 1064 | if (!inetdev_valid_mtu(dev->mtu)) |
1062 | break; | 1065 | break; |
1063 | if (dev->flags & IFF_LOOPBACK) { | 1066 | if (dev->flags & IFF_LOOPBACK) { |
1064 | struct in_ifaddr *ifa; | 1067 | struct in_ifaddr *ifa = inet_alloc_ifa(); |
1065 | if ((ifa = inet_alloc_ifa()) != NULL) { | 1068 | |
1069 | if (ifa) { | ||
1066 | ifa->ifa_local = | 1070 | ifa->ifa_local = |
1067 | ifa->ifa_address = htonl(INADDR_LOOPBACK); | 1071 | ifa->ifa_address = htonl(INADDR_LOOPBACK); |
1068 | ifa->ifa_prefixlen = 8; | 1072 | ifa->ifa_prefixlen = 8; |
@@ -1183,7 +1187,8 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
1183 | goto cont; | 1187 | goto cont; |
1184 | if (idx > s_idx) | 1188 | if (idx > s_idx) |
1185 | s_ip_idx = 0; | 1189 | s_ip_idx = 0; |
1186 | if ((in_dev = __in_dev_get_rtnl(dev)) == NULL) | 1190 | in_dev = __in_dev_get_rtnl(dev); |
1191 | if (!in_dev) | ||
1187 | goto cont; | 1192 | goto cont; |
1188 | 1193 | ||
1189 | for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; | 1194 | for (ifa = in_dev->ifa_list, ip_idx = 0; ifa; |
@@ -1239,18 +1244,18 @@ static void devinet_copy_dflt_conf(struct net *net, int i) | |||
1239 | { | 1244 | { |
1240 | struct net_device *dev; | 1245 | struct net_device *dev; |
1241 | 1246 | ||
1242 | read_lock(&dev_base_lock); | 1247 | rcu_read_lock(); |
1243 | for_each_netdev(net, dev) { | 1248 | for_each_netdev_rcu(net, dev) { |
1244 | struct in_device *in_dev; | 1249 | struct in_device *in_dev; |
1245 | rcu_read_lock(); | 1250 | |
1246 | in_dev = __in_dev_get_rcu(dev); | 1251 | in_dev = __in_dev_get_rcu(dev); |
1247 | if (in_dev && !test_bit(i, in_dev->cnf.state)) | 1252 | if (in_dev && !test_bit(i, in_dev->cnf.state)) |
1248 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; | 1253 | in_dev->cnf.data[i] = net->ipv4.devconf_dflt->data[i]; |
1249 | rcu_read_unlock(); | ||
1250 | } | 1254 | } |
1251 | read_unlock(&dev_base_lock); | 1255 | rcu_read_unlock(); |
1252 | } | 1256 | } |
1253 | 1257 | ||
1258 | /* called with RTNL locked */ | ||
1254 | static void inet_forward_change(struct net *net) | 1259 | static void inet_forward_change(struct net *net) |
1255 | { | 1260 | { |
1256 | struct net_device *dev; | 1261 | struct net_device *dev; |
@@ -1259,7 +1264,6 @@ static void inet_forward_change(struct net *net) | |||
1259 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; | 1264 | IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on; |
1260 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; | 1265 | IPV4_DEVCONF_DFLT(net, FORWARDING) = on; |
1261 | 1266 | ||
1262 | read_lock(&dev_base_lock); | ||
1263 | for_each_netdev(net, dev) { | 1267 | for_each_netdev(net, dev) { |
1264 | struct in_device *in_dev; | 1268 | struct in_device *in_dev; |
1265 | if (on) | 1269 | if (on) |
@@ -1270,7 +1274,6 @@ static void inet_forward_change(struct net *net) | |||
1270 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); | 1274 | IN_DEV_CONF_SET(in_dev, FORWARDING, on); |
1271 | rcu_read_unlock(); | 1275 | rcu_read_unlock(); |
1272 | } | 1276 | } |
1273 | read_unlock(&dev_base_lock); | ||
1274 | } | 1277 | } |
1275 | 1278 | ||
1276 | static int devinet_conf_proc(ctl_table *ctl, int write, | 1279 | static int devinet_conf_proc(ctl_table *ctl, int write, |
@@ -1680,8 +1683,3 @@ void __init devinet_init(void) | |||
1680 | rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); | 1683 | rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr); |
1681 | } | 1684 | } |
1682 | 1685 | ||
1683 | EXPORT_SYMBOL(in_dev_finish_destroy); | ||
1684 | EXPORT_SYMBOL(inet_select_addr); | ||
1685 | EXPORT_SYMBOL(inetdev_by_index); | ||
1686 | EXPORT_SYMBOL(register_inetaddr_notifier); | ||
1687 | EXPORT_SYMBOL(unregister_inetaddr_notifier); | ||
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index f73dbed0f0d7..816e2180bd60 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -229,14 +229,17 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, | |||
229 | */ | 229 | */ |
230 | 230 | ||
231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 231 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, |
232 | struct net_device *dev, __be32 *spec_dst, u32 *itag) | 232 | struct net_device *dev, __be32 *spec_dst, |
233 | u32 *itag, u32 mark) | ||
233 | { | 234 | { |
234 | struct in_device *in_dev; | 235 | struct in_device *in_dev; |
235 | struct flowi fl = { .nl_u = { .ip4_u = | 236 | struct flowi fl = { .nl_u = { .ip4_u = |
236 | { .daddr = src, | 237 | { .daddr = src, |
237 | .saddr = dst, | 238 | .saddr = dst, |
238 | .tos = tos } }, | 239 | .tos = tos } }, |
240 | .mark = mark, | ||
239 | .iif = oif }; | 241 | .iif = oif }; |
242 | |||
240 | struct fib_result res; | 243 | struct fib_result res; |
241 | int no_addr, rpf; | 244 | int no_addr, rpf; |
242 | int ret; | 245 | int ret; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 84adb5754c96..fe11f60ce41b 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -501,15 +501,16 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
501 | if (!(rt->rt_flags & RTCF_LOCAL)) { | 501 | if (!(rt->rt_flags & RTCF_LOCAL)) { |
502 | struct net_device *dev = NULL; | 502 | struct net_device *dev = NULL; |
503 | 503 | ||
504 | rcu_read_lock(); | ||
504 | if (rt->fl.iif && | 505 | if (rt->fl.iif && |
505 | net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr) | 506 | net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr) |
506 | dev = dev_get_by_index(net, rt->fl.iif); | 507 | dev = dev_get_by_index_rcu(net, rt->fl.iif); |
507 | 508 | ||
508 | if (dev) { | 509 | if (dev) |
509 | saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 510 | saddr = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
510 | dev_put(dev); | 511 | else |
511 | } else | ||
512 | saddr = 0; | 512 | saddr = 0; |
513 | rcu_read_unlock(); | ||
513 | } | 514 | } |
514 | 515 | ||
515 | tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) | | 516 | tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) | |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 575f9bd51ccd..b007f8af6e1f 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -206,10 +206,11 @@ static void ip_expire(unsigned long arg) | |||
206 | struct sk_buff *head = qp->q.fragments; | 206 | struct sk_buff *head = qp->q.fragments; |
207 | 207 | ||
208 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 208 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
209 | if ((head->dev = dev_get_by_index(net, qp->iif)) != NULL) { | 209 | rcu_read_lock(); |
210 | head->dev = dev_get_by_index_rcu(net, qp->iif); | ||
211 | if (head->dev) | ||
210 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 212 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
211 | dev_put(head->dev); | 213 | rcu_read_unlock(); |
212 | } | ||
213 | } | 214 | } |
214 | out: | 215 | out: |
215 | spin_unlock(&qp->q.lock); | 216 | spin_unlock(&qp->q.lock); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index a77807d449e3..a7de9e3a8f18 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1476,14 +1476,14 @@ static void ipgre_tap_setup(struct net_device *dev) | |||
1476 | 1476 | ||
1477 | ether_setup(dev); | 1477 | ether_setup(dev); |
1478 | 1478 | ||
1479 | dev->netdev_ops = &ipgre_netdev_ops; | 1479 | dev->netdev_ops = &ipgre_tap_netdev_ops; |
1480 | dev->destructor = free_netdev; | 1480 | dev->destructor = free_netdev; |
1481 | 1481 | ||
1482 | dev->iflink = 0; | 1482 | dev->iflink = 0; |
1483 | dev->features |= NETIF_F_NETNS_LOCAL; | 1483 | dev->features |= NETIF_F_NETNS_LOCAL; |
1484 | } | 1484 | } |
1485 | 1485 | ||
1486 | static int ipgre_newlink(struct net_device *dev, struct nlattr *tb[], | 1486 | static int ipgre_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], |
1487 | struct nlattr *data[]) | 1487 | struct nlattr *data[]) |
1488 | { | 1488 | { |
1489 | struct ip_tunnel *nt; | 1489 | struct ip_tunnel *nt; |
@@ -1537,25 +1537,29 @@ static int ipgre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
1537 | if (t->dev != dev) | 1537 | if (t->dev != dev) |
1538 | return -EEXIST; | 1538 | return -EEXIST; |
1539 | } else { | 1539 | } else { |
1540 | unsigned nflags = 0; | ||
1541 | |||
1542 | t = nt; | 1540 | t = nt; |
1543 | 1541 | ||
1544 | if (ipv4_is_multicast(p.iph.daddr)) | 1542 | if (dev->type != ARPHRD_ETHER) { |
1545 | nflags = IFF_BROADCAST; | 1543 | unsigned nflags = 0; |
1546 | else if (p.iph.daddr) | ||
1547 | nflags = IFF_POINTOPOINT; | ||
1548 | 1544 | ||
1549 | if ((dev->flags ^ nflags) & | 1545 | if (ipv4_is_multicast(p.iph.daddr)) |
1550 | (IFF_POINTOPOINT | IFF_BROADCAST)) | 1546 | nflags = IFF_BROADCAST; |
1551 | return -EINVAL; | 1547 | else if (p.iph.daddr) |
1548 | nflags = IFF_POINTOPOINT; | ||
1549 | |||
1550 | if ((dev->flags ^ nflags) & | ||
1551 | (IFF_POINTOPOINT | IFF_BROADCAST)) | ||
1552 | return -EINVAL; | ||
1553 | } | ||
1552 | 1554 | ||
1553 | ipgre_tunnel_unlink(ign, t); | 1555 | ipgre_tunnel_unlink(ign, t); |
1554 | t->parms.iph.saddr = p.iph.saddr; | 1556 | t->parms.iph.saddr = p.iph.saddr; |
1555 | t->parms.iph.daddr = p.iph.daddr; | 1557 | t->parms.iph.daddr = p.iph.daddr; |
1556 | t->parms.i_key = p.i_key; | 1558 | t->parms.i_key = p.i_key; |
1557 | memcpy(dev->dev_addr, &p.iph.saddr, 4); | 1559 | if (dev->type != ARPHRD_ETHER) { |
1558 | memcpy(dev->broadcast, &p.iph.daddr, 4); | 1560 | memcpy(dev->dev_addr, &p.iph.saddr, 4); |
1561 | memcpy(dev->broadcast, &p.iph.daddr, 4); | ||
1562 | } | ||
1559 | ipgre_tunnel_link(ign, t); | 1563 | ipgre_tunnel_link(ign, t); |
1560 | netdev_state_change(dev); | 1564 | netdev_state_change(dev); |
1561 | } | 1565 | } |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index a2ca53da4372..c5b1f71c3cd8 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -446,25 +446,27 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
446 | goto tx_error; | 446 | goto tx_error; |
447 | } | 447 | } |
448 | 448 | ||
449 | if (tiph->frag_off) | 449 | df |= old_iph->frag_off & htons(IP_DF); |
450 | |||
451 | if (df) { | ||
450 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); | 452 | mtu = dst_mtu(&rt->u.dst) - sizeof(struct iphdr); |
451 | else | ||
452 | mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; | ||
453 | 453 | ||
454 | if (mtu < 68) { | 454 | if (mtu < 68) { |
455 | stats->collisions++; | 455 | stats->collisions++; |
456 | ip_rt_put(rt); | 456 | ip_rt_put(rt); |
457 | goto tx_error; | 457 | goto tx_error; |
458 | } | 458 | } |
459 | if (skb_dst(skb)) | ||
460 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); | ||
461 | 459 | ||
462 | df |= (old_iph->frag_off&htons(IP_DF)); | 460 | if (skb_dst(skb)) |
461 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), mtu); | ||
463 | 462 | ||
464 | if ((old_iph->frag_off&htons(IP_DF)) && mtu < ntohs(old_iph->tot_len)) { | 463 | if ((old_iph->frag_off & htons(IP_DF)) && |
465 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); | 464 | mtu < ntohs(old_iph->tot_len)) { |
466 | ip_rt_put(rt); | 465 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
467 | goto tx_error; | 466 | htonl(mtu)); |
467 | ip_rt_put(rt); | ||
468 | goto tx_error; | ||
469 | } | ||
468 | } | 470 | } |
469 | 471 | ||
470 | if (tunnel->err_count > 0) { | 472 | if (tunnel->err_count > 0) { |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 68afc6ecd343..fe1a64479dd0 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -750,6 +750,8 @@ static int __init nf_nat_init(void) | |||
750 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); | 750 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
751 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, | 751 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, |
752 | nfnetlink_parse_nat_setup); | 752 | nfnetlink_parse_nat_setup); |
753 | BUG_ON(nf_ct_nat_offset != NULL); | ||
754 | rcu_assign_pointer(nf_ct_nat_offset, nf_nat_get_offset); | ||
753 | return 0; | 755 | return 0; |
754 | 756 | ||
755 | cleanup_extend: | 757 | cleanup_extend: |
@@ -764,6 +766,7 @@ static void __exit nf_nat_cleanup(void) | |||
764 | nf_ct_extend_unregister(&nat_extend); | 766 | nf_ct_extend_unregister(&nat_extend); |
765 | rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); | 767 | rcu_assign_pointer(nf_nat_seq_adjust_hook, NULL); |
766 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL); | 768 | rcu_assign_pointer(nfnetlink_parse_nat_setup_hook, NULL); |
769 | rcu_assign_pointer(nf_ct_nat_offset, NULL); | ||
767 | synchronize_net(); | 770 | synchronize_net(); |
768 | } | 771 | } |
769 | 772 | ||
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 09172a65d9b6..f9520fa3aba9 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -73,6 +73,28 @@ adjust_tcp_sequence(u32 seq, | |||
73 | DUMP_OFFSET(this_way); | 73 | DUMP_OFFSET(this_way); |
74 | } | 74 | } |
75 | 75 | ||
76 | /* Get the offset value, for conntrack */ | ||
77 | s16 nf_nat_get_offset(const struct nf_conn *ct, | ||
78 | enum ip_conntrack_dir dir, | ||
79 | u32 seq) | ||
80 | { | ||
81 | struct nf_conn_nat *nat = nfct_nat(ct); | ||
82 | struct nf_nat_seq *this_way; | ||
83 | s16 offset; | ||
84 | |||
85 | if (!nat) | ||
86 | return 0; | ||
87 | |||
88 | this_way = &nat->seq[dir]; | ||
89 | spin_lock_bh(&nf_nat_seqofs_lock); | ||
90 | offset = after(seq, this_way->correction_pos) | ||
91 | ? this_way->offset_after : this_way->offset_before; | ||
92 | spin_unlock_bh(&nf_nat_seqofs_lock); | ||
93 | |||
94 | return offset; | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(nf_nat_get_offset); | ||
97 | |||
76 | /* Frobs data inside this packet, which is linear. */ | 98 | /* Frobs data inside this packet, which is linear. */ |
77 | static void mangle_contents(struct sk_buff *skb, | 99 | static void mangle_contents(struct sk_buff *skb, |
78 | unsigned int dataoff, | 100 | unsigned int dataoff, |
@@ -189,11 +211,6 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
189 | adjust_tcp_sequence(ntohl(tcph->seq), | 211 | adjust_tcp_sequence(ntohl(tcph->seq), |
190 | (int)rep_len - (int)match_len, | 212 | (int)rep_len - (int)match_len, |
191 | ct, ctinfo); | 213 | ct, ctinfo); |
192 | /* Tell TCP window tracking about seq change */ | ||
193 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), | ||
194 | ct, CTINFO2DIR(ctinfo), | ||
195 | (int)rep_len - (int)match_len); | ||
196 | |||
197 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); | 214 | nf_conntrack_event_cache(IPCT_NATSEQADJ, ct); |
198 | } | 215 | } |
199 | return 1; | 216 | return 1; |
@@ -415,12 +432,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
415 | tcph->seq = newseq; | 432 | tcph->seq = newseq; |
416 | tcph->ack_seq = newack; | 433 | tcph->ack_seq = newack; |
417 | 434 | ||
418 | if (!nf_nat_sack_adjust(skb, tcph, ct, ctinfo)) | 435 | return nf_nat_sack_adjust(skb, tcph, ct, ctinfo); |
419 | return 0; | ||
420 | |||
421 | nf_conntrack_tcp_update(skb, ip_hdrlen(skb), ct, dir, seqoff); | ||
422 | |||
423 | return 1; | ||
424 | } | 436 | } |
425 | 437 | ||
426 | /* Setup NAT on this expected conntrack so it follows master. */ | 438 | /* Setup NAT on this expected conntrack so it follows master. */ |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 68fb22702051..ff258b57680b 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1851,7 +1851,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1851 | goto e_inval; | 1851 | goto e_inval; |
1852 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 1852 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
1853 | } else if (fib_validate_source(saddr, 0, tos, 0, | 1853 | } else if (fib_validate_source(saddr, 0, tos, 0, |
1854 | dev, &spec_dst, &itag) < 0) | 1854 | dev, &spec_dst, &itag, 0) < 0) |
1855 | goto e_inval; | 1855 | goto e_inval; |
1856 | 1856 | ||
1857 | rth = dst_alloc(&ipv4_dst_ops); | 1857 | rth = dst_alloc(&ipv4_dst_ops); |
@@ -1964,7 +1964,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1964 | 1964 | ||
1965 | 1965 | ||
1966 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), | 1966 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), |
1967 | in_dev->dev, &spec_dst, &itag); | 1967 | in_dev->dev, &spec_dst, &itag, skb->mark); |
1968 | if (err < 0) { | 1968 | if (err < 0) { |
1969 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, | 1969 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, |
1970 | saddr); | 1970 | saddr); |
@@ -2138,7 +2138,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2138 | int result; | 2138 | int result; |
2139 | result = fib_validate_source(saddr, daddr, tos, | 2139 | result = fib_validate_source(saddr, daddr, tos, |
2140 | net->loopback_dev->ifindex, | 2140 | net->loopback_dev->ifindex, |
2141 | dev, &spec_dst, &itag); | 2141 | dev, &spec_dst, &itag, skb->mark); |
2142 | if (result < 0) | 2142 | if (result < 0) |
2143 | goto martian_source; | 2143 | goto martian_source; |
2144 | if (result) | 2144 | if (result) |
@@ -2167,7 +2167,7 @@ brd_input: | |||
2167 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 2167 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
2168 | else { | 2168 | else { |
2169 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 2169 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, |
2170 | &itag); | 2170 | &itag, skb->mark); |
2171 | if (err < 0) | 2171 | if (err < 0) |
2172 | goto martian_source; | 2172 | goto martian_source; |
2173 | if (err) | 2173 | if (err) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index ba0eab65fe80..be0c5bf7bfca 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -3704,8 +3704,6 @@ void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received *opt_rx, | |||
3704 | struct tcphdr *th = tcp_hdr(skb); | 3704 | struct tcphdr *th = tcp_hdr(skb); |
3705 | int length = (th->doff * 4) - sizeof(struct tcphdr); | 3705 | int length = (th->doff * 4) - sizeof(struct tcphdr); |
3706 | 3706 | ||
3707 | BUG_ON(!estab && !dst); | ||
3708 | |||
3709 | ptr = (unsigned char *)(th + 1); | 3707 | ptr = (unsigned char *)(th + 1); |
3710 | opt_rx->saw_tstamp = 0; | 3708 | opt_rx->saw_tstamp = 0; |
3711 | 3709 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 463d51b53d37..a9d34e224cb6 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -500,11 +500,10 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
500 | int paws_reject = 0; | 500 | int paws_reject = 0; |
501 | struct tcp_options_received tmp_opt; | 501 | struct tcp_options_received tmp_opt; |
502 | struct sock *child; | 502 | struct sock *child; |
503 | struct dst_entry *dst = inet_csk_route_req(sk, req); | ||
504 | 503 | ||
505 | tmp_opt.saw_tstamp = 0; | 504 | if ((th->doff > (sizeof(struct tcphdr)>>2)) && (req->ts_recent)) { |
506 | if (th->doff > (sizeof(struct tcphdr)>>2)) { | 505 | tmp_opt.tstamp_ok = 1; |
507 | tcp_parse_options(skb, &tmp_opt, 0, dst); | 506 | tcp_parse_options(skb, &tmp_opt, 1, NULL); |
508 | 507 | ||
509 | if (tmp_opt.saw_tstamp) { | 508 | if (tmp_opt.saw_tstamp) { |
510 | tmp_opt.ts_recent = req->ts_recent; | 509 | tmp_opt.ts_recent = req->ts_recent; |
@@ -517,8 +516,6 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
517 | } | 516 | } |
518 | } | 517 | } |
519 | 518 | ||
520 | dst_release(dst); | ||
521 | |||
522 | /* Check for pure retransmitted SYN. */ | 519 | /* Check for pure retransmitted SYN. */ |
523 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn && | 520 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn && |
524 | flg == TCP_FLAG_SYN && | 521 | flg == TCP_FLAG_SYN && |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4274c1cc78fd..d73e9170536b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -138,13 +138,14 @@ static int udp_lib_lport_inuse(struct net *net, __u16 num, | |||
138 | sk_nulls_for_each(sk2, node, &hslot->head) | 138 | sk_nulls_for_each(sk2, node, &hslot->head) |
139 | if (net_eq(sock_net(sk2), net) && | 139 | if (net_eq(sock_net(sk2), net) && |
140 | sk2 != sk && | 140 | sk2 != sk && |
141 | (bitmap || sk2->sk_hash == num) && | 141 | (bitmap || udp_sk(sk2)->udp_port_hash == num) && |
142 | (!sk2->sk_reuse || !sk->sk_reuse) && | 142 | (!sk2->sk_reuse || !sk->sk_reuse) && |
143 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if | 143 | (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if |
144 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && | 144 | || sk2->sk_bound_dev_if == sk->sk_bound_dev_if) && |
145 | (*saddr_comp)(sk, sk2)) { | 145 | (*saddr_comp)(sk, sk2)) { |
146 | if (bitmap) | 146 | if (bitmap) |
147 | __set_bit(sk2->sk_hash >> log, bitmap); | 147 | __set_bit(udp_sk(sk2)->udp_port_hash >> log, |
148 | bitmap); | ||
148 | else | 149 | else |
149 | return 1; | 150 | return 1; |
150 | } | 151 | } |
@@ -162,7 +163,7 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
162 | int (*saddr_comp)(const struct sock *sk1, | 163 | int (*saddr_comp)(const struct sock *sk1, |
163 | const struct sock *sk2)) | 164 | const struct sock *sk2)) |
164 | { | 165 | { |
165 | struct udp_hslot *hslot; | 166 | struct udp_hslot *hslot, *hslot2; |
166 | struct udp_table *udptable = sk->sk_prot->h.udp_table; | 167 | struct udp_table *udptable = sk->sk_prot->h.udp_table; |
167 | int error = 1; | 168 | int error = 1; |
168 | struct net *net = sock_net(sk); | 169 | struct net *net = sock_net(sk); |
@@ -215,10 +216,19 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum, | |||
215 | } | 216 | } |
216 | found: | 217 | found: |
217 | inet_sk(sk)->inet_num = snum; | 218 | inet_sk(sk)->inet_num = snum; |
218 | sk->sk_hash = snum; | 219 | udp_sk(sk)->udp_port_hash = snum; |
220 | udp_sk(sk)->udp_portaddr_hash ^= snum; | ||
219 | if (sk_unhashed(sk)) { | 221 | if (sk_unhashed(sk)) { |
220 | sk_nulls_add_node_rcu(sk, &hslot->head); | 222 | sk_nulls_add_node_rcu(sk, &hslot->head); |
223 | hslot->count++; | ||
221 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 224 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); |
225 | |||
226 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | ||
227 | spin_lock(&hslot2->lock); | ||
228 | hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node, | ||
229 | &hslot2->head); | ||
230 | hslot2->count++; | ||
231 | spin_unlock(&hslot2->lock); | ||
222 | } | 232 | } |
223 | error = 0; | 233 | error = 0; |
224 | fail_unlock: | 234 | fail_unlock: |
@@ -237,8 +247,19 @@ static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2) | |||
237 | inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)); | 247 | inet1->inet_rcv_saddr == inet2->inet_rcv_saddr)); |
238 | } | 248 | } |
239 | 249 | ||
250 | static unsigned int udp4_portaddr_hash(struct net *net, __be32 saddr, | ||
251 | unsigned int port) | ||
252 | { | ||
253 | return jhash_1word(saddr, net_hash_mix(net)) ^ port; | ||
254 | } | ||
255 | |||
240 | int udp_v4_get_port(struct sock *sk, unsigned short snum) | 256 | int udp_v4_get_port(struct sock *sk, unsigned short snum) |
241 | { | 257 | { |
258 | /* precompute partial secondary hash */ | ||
259 | udp_sk(sk)->udp_portaddr_hash = | ||
260 | udp4_portaddr_hash(sock_net(sk), | ||
261 | inet_sk(sk)->inet_rcv_saddr, | ||
262 | 0); | ||
242 | return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); | 263 | return udp_lib_get_port(sk, snum, ipv4_rcv_saddr_equal); |
243 | } | 264 | } |
244 | 265 | ||
@@ -248,7 +269,7 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr, | |||
248 | { | 269 | { |
249 | int score = -1; | 270 | int score = -1; |
250 | 271 | ||
251 | if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && | 272 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && |
252 | !ipv6_only_sock(sk)) { | 273 | !ipv6_only_sock(sk)) { |
253 | struct inet_sock *inet = inet_sk(sk); | 274 | struct inet_sock *inet = inet_sk(sk); |
254 | 275 | ||
@@ -277,6 +298,91 @@ static inline int compute_score(struct sock *sk, struct net *net, __be32 saddr, | |||
277 | return score; | 298 | return score; |
278 | } | 299 | } |
279 | 300 | ||
301 | /* | ||
302 | * In this second variant, we check (daddr, dport) matches (inet_rcv_sadd, inet_num) | ||
303 | */ | ||
304 | #define SCORE2_MAX (1 + 2 + 2 + 2) | ||
305 | static inline int compute_score2(struct sock *sk, struct net *net, | ||
306 | __be32 saddr, __be16 sport, | ||
307 | __be32 daddr, unsigned int hnum, int dif) | ||
308 | { | ||
309 | int score = -1; | ||
310 | |||
311 | if (net_eq(sock_net(sk), net) && !ipv6_only_sock(sk)) { | ||
312 | struct inet_sock *inet = inet_sk(sk); | ||
313 | |||
314 | if (inet->inet_rcv_saddr != daddr) | ||
315 | return -1; | ||
316 | if (inet->inet_num != hnum) | ||
317 | return -1; | ||
318 | |||
319 | score = (sk->sk_family == PF_INET ? 1 : 0); | ||
320 | if (inet->inet_daddr) { | ||
321 | if (inet->inet_daddr != saddr) | ||
322 | return -1; | ||
323 | score += 2; | ||
324 | } | ||
325 | if (inet->inet_dport) { | ||
326 | if (inet->inet_dport != sport) | ||
327 | return -1; | ||
328 | score += 2; | ||
329 | } | ||
330 | if (sk->sk_bound_dev_if) { | ||
331 | if (sk->sk_bound_dev_if != dif) | ||
332 | return -1; | ||
333 | score += 2; | ||
334 | } | ||
335 | } | ||
336 | return score; | ||
337 | } | ||
338 | |||
339 | #define udp_portaddr_for_each_entry_rcu(__sk, node, list) \ | ||
340 | hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node) | ||
341 | |||
342 | /* called with read_rcu_lock() */ | ||
343 | static struct sock *udp4_lib_lookup2(struct net *net, | ||
344 | __be32 saddr, __be16 sport, | ||
345 | __be32 daddr, unsigned int hnum, int dif, | ||
346 | struct udp_hslot *hslot2, unsigned int slot2) | ||
347 | { | ||
348 | struct sock *sk, *result; | ||
349 | struct hlist_nulls_node *node; | ||
350 | int score, badness; | ||
351 | |||
352 | begin: | ||
353 | result = NULL; | ||
354 | badness = -1; | ||
355 | udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { | ||
356 | score = compute_score2(sk, net, saddr, sport, | ||
357 | daddr, hnum, dif); | ||
358 | if (score > badness) { | ||
359 | result = sk; | ||
360 | badness = score; | ||
361 | if (score == SCORE2_MAX) | ||
362 | goto exact_match; | ||
363 | } | ||
364 | } | ||
365 | /* | ||
366 | * if the nulls value we got at the end of this lookup is | ||
367 | * not the expected one, we must restart lookup. | ||
368 | * We probably met an item that was moved to another chain. | ||
369 | */ | ||
370 | if (get_nulls_value(node) != slot2) | ||
371 | goto begin; | ||
372 | |||
373 | if (result) { | ||
374 | exact_match: | ||
375 | if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) | ||
376 | result = NULL; | ||
377 | else if (unlikely(compute_score2(result, net, saddr, sport, | ||
378 | daddr, hnum, dif) < badness)) { | ||
379 | sock_put(result); | ||
380 | goto begin; | ||
381 | } | ||
382 | } | ||
383 | return result; | ||
384 | } | ||
385 | |||
280 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try | 386 | /* UDP is nearly always wildcards out the wazoo, it makes no sense to try |
281 | * harder than this. -DaveM | 387 | * harder than this. -DaveM |
282 | */ | 388 | */ |
@@ -287,11 +393,35 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
287 | struct sock *sk, *result; | 393 | struct sock *sk, *result; |
288 | struct hlist_nulls_node *node; | 394 | struct hlist_nulls_node *node; |
289 | unsigned short hnum = ntohs(dport); | 395 | unsigned short hnum = ntohs(dport); |
290 | unsigned int hash = udp_hashfn(net, hnum, udptable->mask); | 396 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); |
291 | struct udp_hslot *hslot = &udptable->hash[hash]; | 397 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; |
292 | int score, badness; | 398 | int score, badness; |
293 | 399 | ||
294 | rcu_read_lock(); | 400 | rcu_read_lock(); |
401 | if (hslot->count > 10) { | ||
402 | hash2 = udp4_portaddr_hash(net, daddr, hnum); | ||
403 | slot2 = hash2 & udptable->mask; | ||
404 | hslot2 = &udptable->hash2[slot2]; | ||
405 | if (hslot->count < hslot2->count) | ||
406 | goto begin; | ||
407 | |||
408 | result = udp4_lib_lookup2(net, saddr, sport, | ||
409 | daddr, hnum, dif, | ||
410 | hslot2, slot2); | ||
411 | if (!result) { | ||
412 | hash2 = udp4_portaddr_hash(net, INADDR_ANY, hnum); | ||
413 | slot2 = hash2 & udptable->mask; | ||
414 | hslot2 = &udptable->hash2[slot2]; | ||
415 | if (hslot->count < hslot2->count) | ||
416 | goto begin; | ||
417 | |||
418 | result = udp4_lib_lookup2(net, INADDR_ANY, sport, | ||
419 | daddr, hnum, dif, | ||
420 | hslot2, slot2); | ||
421 | } | ||
422 | rcu_read_unlock(); | ||
423 | return result; | ||
424 | } | ||
295 | begin: | 425 | begin: |
296 | result = NULL; | 426 | result = NULL; |
297 | badness = -1; | 427 | badness = -1; |
@@ -308,7 +438,7 @@ begin: | |||
308 | * not the expected one, we must restart lookup. | 438 | * not the expected one, we must restart lookup. |
309 | * We probably met an item that was moved to another chain. | 439 | * We probably met an item that was moved to another chain. |
310 | */ | 440 | */ |
311 | if (get_nulls_value(node) != hash) | 441 | if (get_nulls_value(node) != slot) |
312 | goto begin; | 442 | goto begin; |
313 | 443 | ||
314 | if (result) { | 444 | if (result) { |
@@ -359,7 +489,7 @@ static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, | |||
359 | struct inet_sock *inet = inet_sk(s); | 489 | struct inet_sock *inet = inet_sk(s); |
360 | 490 | ||
361 | if (!net_eq(sock_net(s), net) || | 491 | if (!net_eq(sock_net(s), net) || |
362 | s->sk_hash != hnum || | 492 | udp_sk(s)->udp_port_hash != hnum || |
363 | (inet->inet_daddr && inet->inet_daddr != rmt_addr) || | 493 | (inet->inet_daddr && inet->inet_daddr != rmt_addr) || |
364 | (inet->inet_dport != rmt_port && inet->inet_dport) || | 494 | (inet->inet_dport != rmt_port && inet->inet_dport) || |
365 | (inet->inet_rcv_saddr && | 495 | (inet->inet_rcv_saddr && |
@@ -1005,9 +1135,7 @@ try_again: | |||
1005 | err = ulen; | 1135 | err = ulen; |
1006 | 1136 | ||
1007 | out_free: | 1137 | out_free: |
1008 | lock_sock(sk); | 1138 | skb_free_datagram_locked(sk, skb); |
1009 | skb_free_datagram(sk, skb); | ||
1010 | release_sock(sk); | ||
1011 | out: | 1139 | out: |
1012 | return err; | 1140 | return err; |
1013 | 1141 | ||
@@ -1050,13 +1178,22 @@ void udp_lib_unhash(struct sock *sk) | |||
1050 | { | 1178 | { |
1051 | if (sk_hashed(sk)) { | 1179 | if (sk_hashed(sk)) { |
1052 | struct udp_table *udptable = sk->sk_prot->h.udp_table; | 1180 | struct udp_table *udptable = sk->sk_prot->h.udp_table; |
1053 | struct udp_hslot *hslot = udp_hashslot(udptable, sock_net(sk), | 1181 | struct udp_hslot *hslot, *hslot2; |
1054 | sk->sk_hash); | 1182 | |
1183 | hslot = udp_hashslot(udptable, sock_net(sk), | ||
1184 | udp_sk(sk)->udp_port_hash); | ||
1185 | hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash); | ||
1055 | 1186 | ||
1056 | spin_lock_bh(&hslot->lock); | 1187 | spin_lock_bh(&hslot->lock); |
1057 | if (sk_nulls_del_node_init_rcu(sk)) { | 1188 | if (sk_nulls_del_node_init_rcu(sk)) { |
1189 | hslot->count--; | ||
1058 | inet_sk(sk)->inet_num = 0; | 1190 | inet_sk(sk)->inet_num = 0; |
1059 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | 1191 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); |
1192 | |||
1193 | spin_lock(&hslot2->lock); | ||
1194 | hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node); | ||
1195 | hslot2->count--; | ||
1196 | spin_unlock(&hslot2->lock); | ||
1060 | } | 1197 | } |
1061 | spin_unlock_bh(&hslot->lock); | 1198 | spin_unlock_bh(&hslot->lock); |
1062 | } | 1199 | } |
@@ -1192,49 +1329,83 @@ drop: | |||
1192 | return -1; | 1329 | return -1; |
1193 | } | 1330 | } |
1194 | 1331 | ||
1332 | |||
1333 | static void flush_stack(struct sock **stack, unsigned int count, | ||
1334 | struct sk_buff *skb, unsigned int final) | ||
1335 | { | ||
1336 | unsigned int i; | ||
1337 | struct sk_buff *skb1 = NULL; | ||
1338 | struct sock *sk; | ||
1339 | |||
1340 | for (i = 0; i < count; i++) { | ||
1341 | sk = stack[i]; | ||
1342 | if (likely(skb1 == NULL)) | ||
1343 | skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); | ||
1344 | |||
1345 | if (!skb1) { | ||
1346 | atomic_inc(&sk->sk_drops); | ||
1347 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | ||
1348 | IS_UDPLITE(sk)); | ||
1349 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_INERRORS, | ||
1350 | IS_UDPLITE(sk)); | ||
1351 | } | ||
1352 | |||
1353 | if (skb1 && udp_queue_rcv_skb(sk, skb1) <= 0) | ||
1354 | skb1 = NULL; | ||
1355 | } | ||
1356 | if (unlikely(skb1)) | ||
1357 | kfree_skb(skb1); | ||
1358 | } | ||
1359 | |||
1195 | /* | 1360 | /* |
1196 | * Multicasts and broadcasts go to each listener. | 1361 | * Multicasts and broadcasts go to each listener. |
1197 | * | 1362 | * |
1198 | * Note: called only from the BH handler context, | 1363 | * Note: called only from the BH handler context. |
1199 | * so we don't need to lock the hashes. | ||
1200 | */ | 1364 | */ |
1201 | static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | 1365 | static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
1202 | struct udphdr *uh, | 1366 | struct udphdr *uh, |
1203 | __be32 saddr, __be32 daddr, | 1367 | __be32 saddr, __be32 daddr, |
1204 | struct udp_table *udptable) | 1368 | struct udp_table *udptable) |
1205 | { | 1369 | { |
1206 | struct sock *sk; | 1370 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
1207 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); | 1371 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); |
1208 | int dif; | 1372 | int dif; |
1373 | unsigned int i, count = 0; | ||
1209 | 1374 | ||
1210 | spin_lock(&hslot->lock); | 1375 | spin_lock(&hslot->lock); |
1211 | sk = sk_nulls_head(&hslot->head); | 1376 | sk = sk_nulls_head(&hslot->head); |
1212 | dif = skb->dev->ifindex; | 1377 | dif = skb->dev->ifindex; |
1213 | sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 1378 | sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
1214 | if (sk) { | 1379 | while (sk) { |
1215 | struct sock *sknext = NULL; | 1380 | stack[count++] = sk; |
1216 | 1381 | sk = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest, | |
1217 | do { | 1382 | daddr, uh->source, saddr, dif); |
1218 | struct sk_buff *skb1 = skb; | 1383 | if (unlikely(count == ARRAY_SIZE(stack))) { |
1219 | 1384 | if (!sk) | |
1220 | sknext = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest, | 1385 | break; |
1221 | daddr, uh->source, saddr, | 1386 | flush_stack(stack, count, skb, ~0); |
1222 | dif); | 1387 | count = 0; |
1223 | if (sknext) | 1388 | } |
1224 | skb1 = skb_clone(skb, GFP_ATOMIC); | 1389 | } |
1225 | 1390 | /* | |
1226 | if (skb1) { | 1391 | * before releasing chain lock, we must take a reference on sockets |
1227 | int ret = udp_queue_rcv_skb(sk, skb1); | 1392 | */ |
1228 | if (ret > 0) | 1393 | for (i = 0; i < count; i++) |
1229 | /* we should probably re-process instead | 1394 | sock_hold(stack[i]); |
1230 | * of dropping packets here. */ | 1395 | |
1231 | kfree_skb(skb1); | ||
1232 | } | ||
1233 | sk = sknext; | ||
1234 | } while (sknext); | ||
1235 | } else | ||
1236 | consume_skb(skb); | ||
1237 | spin_unlock(&hslot->lock); | 1396 | spin_unlock(&hslot->lock); |
1397 | |||
1398 | /* | ||
1399 | * do the slow work with no lock held | ||
1400 | */ | ||
1401 | if (count) { | ||
1402 | flush_stack(stack, count, skb, count - 1); | ||
1403 | |||
1404 | for (i = 0; i < count; i++) | ||
1405 | sock_put(stack[i]); | ||
1406 | } else { | ||
1407 | kfree_skb(skb); | ||
1408 | } | ||
1238 | return 0; | 1409 | return 0; |
1239 | } | 1410 | } |
1240 | 1411 | ||
@@ -1844,7 +2015,7 @@ void __init udp_table_init(struct udp_table *table, const char *name) | |||
1844 | 2015 | ||
1845 | if (!CONFIG_BASE_SMALL) | 2016 | if (!CONFIG_BASE_SMALL) |
1846 | table->hash = alloc_large_system_hash(name, | 2017 | table->hash = alloc_large_system_hash(name, |
1847 | sizeof(struct udp_hslot), | 2018 | 2 * sizeof(struct udp_hslot), |
1848 | uhash_entries, | 2019 | uhash_entries, |
1849 | 21, /* one slot per 2 MB */ | 2020 | 21, /* one slot per 2 MB */ |
1850 | 0, | 2021 | 0, |
@@ -1856,16 +2027,23 @@ void __init udp_table_init(struct udp_table *table, const char *name) | |||
1856 | */ | 2027 | */ |
1857 | if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) { | 2028 | if (CONFIG_BASE_SMALL || table->mask < UDP_HTABLE_SIZE_MIN - 1) { |
1858 | table->hash = kmalloc(UDP_HTABLE_SIZE_MIN * | 2029 | table->hash = kmalloc(UDP_HTABLE_SIZE_MIN * |
1859 | sizeof(struct udp_hslot), GFP_KERNEL); | 2030 | 2 * sizeof(struct udp_hslot), GFP_KERNEL); |
1860 | if (!table->hash) | 2031 | if (!table->hash) |
1861 | panic(name); | 2032 | panic(name); |
1862 | table->log = ilog2(UDP_HTABLE_SIZE_MIN); | 2033 | table->log = ilog2(UDP_HTABLE_SIZE_MIN); |
1863 | table->mask = UDP_HTABLE_SIZE_MIN - 1; | 2034 | table->mask = UDP_HTABLE_SIZE_MIN - 1; |
1864 | } | 2035 | } |
2036 | table->hash2 = table->hash + (table->mask + 1); | ||
1865 | for (i = 0; i <= table->mask; i++) { | 2037 | for (i = 0; i <= table->mask; i++) { |
1866 | INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); | 2038 | INIT_HLIST_NULLS_HEAD(&table->hash[i].head, i); |
2039 | table->hash[i].count = 0; | ||
1867 | spin_lock_init(&table->hash[i].lock); | 2040 | spin_lock_init(&table->hash[i].lock); |
1868 | } | 2041 | } |
2042 | for (i = 0; i <= table->mask; i++) { | ||
2043 | INIT_HLIST_NULLS_HEAD(&table->hash2[i].head, i); | ||
2044 | table->hash2[i].count = 0; | ||
2045 | spin_lock_init(&table->hash2[i].lock); | ||
2046 | } | ||
1869 | } | 2047 | } |
1870 | 2048 | ||
1871 | void __init udp_init(void) | 2049 | void __init udp_init(void) |
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c index 470c504b9554..66f79513f4a5 100644 --- a/net/ipv4/udplite.c +++ b/net/ipv4/udplite.c | |||
@@ -64,7 +64,6 @@ static struct inet_protosw udplite4_protosw = { | |||
64 | .protocol = IPPROTO_UDPLITE, | 64 | .protocol = IPPROTO_UDPLITE, |
65 | .prot = &udplite_prot, | 65 | .prot = &udplite_prot, |
66 | .ops = &inet_dgram_ops, | 66 | .ops = &inet_dgram_ops, |
67 | .capability = -1, | ||
68 | .no_check = 0, /* must checksum (RFC 3828) */ | 67 | .no_check = 0, /* must checksum (RFC 3828) */ |
69 | .flags = INET_PROTOSW_PERMANENT, | 68 | .flags = INET_PROTOSW_PERMANENT, |
70 | }; | 69 | }; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 918648409612..024bba30de21 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -481,9 +481,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
481 | struct net_device *dev; | 481 | struct net_device *dev; |
482 | struct inet6_dev *idev; | 482 | struct inet6_dev *idev; |
483 | 483 | ||
484 | read_lock(&dev_base_lock); | 484 | rcu_read_lock(); |
485 | for_each_netdev(net, dev) { | 485 | for_each_netdev_rcu(net, dev) { |
486 | rcu_read_lock(); | ||
487 | idev = __in6_dev_get(dev); | 486 | idev = __in6_dev_get(dev); |
488 | if (idev) { | 487 | if (idev) { |
489 | int changed = (!idev->cnf.forwarding) ^ (!newf); | 488 | int changed = (!idev->cnf.forwarding) ^ (!newf); |
@@ -491,9 +490,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
491 | if (changed) | 490 | if (changed) |
492 | dev_forward_change(idev); | 491 | dev_forward_change(idev); |
493 | } | 492 | } |
494 | rcu_read_unlock(); | ||
495 | } | 493 | } |
496 | read_unlock(&dev_base_lock); | 494 | rcu_read_unlock(); |
497 | } | 495 | } |
498 | 496 | ||
499 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 497 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) |
@@ -1137,10 +1135,9 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1137 | hiscore->rule = -1; | 1135 | hiscore->rule = -1; |
1138 | hiscore->ifa = NULL; | 1136 | hiscore->ifa = NULL; |
1139 | 1137 | ||
1140 | read_lock(&dev_base_lock); | ||
1141 | rcu_read_lock(); | 1138 | rcu_read_lock(); |
1142 | 1139 | ||
1143 | for_each_netdev(net, dev) { | 1140 | for_each_netdev_rcu(net, dev) { |
1144 | struct inet6_dev *idev; | 1141 | struct inet6_dev *idev; |
1145 | 1142 | ||
1146 | /* Candidate Source Address (section 4) | 1143 | /* Candidate Source Address (section 4) |
@@ -1235,7 +1232,6 @@ try_nextdev: | |||
1235 | read_unlock_bh(&idev->lock); | 1232 | read_unlock_bh(&idev->lock); |
1236 | } | 1233 | } |
1237 | rcu_read_unlock(); | 1234 | rcu_read_unlock(); |
1238 | read_unlock(&dev_base_lock); | ||
1239 | 1235 | ||
1240 | if (!hiscore->ifa) | 1236 | if (!hiscore->ifa) |
1241 | return -EADDRNOTAVAIL; | 1237 | return -EADDRNOTAVAIL; |
@@ -4052,9 +4048,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
4052 | struct net_device *dev; | 4048 | struct net_device *dev; |
4053 | struct inet6_dev *idev; | 4049 | struct inet6_dev *idev; |
4054 | 4050 | ||
4055 | read_lock(&dev_base_lock); | 4051 | rcu_read_lock(); |
4056 | for_each_netdev(net, dev) { | 4052 | for_each_netdev_rcu(net, dev) { |
4057 | rcu_read_lock(); | ||
4058 | idev = __in6_dev_get(dev); | 4053 | idev = __in6_dev_get(dev); |
4059 | if (idev) { | 4054 | if (idev) { |
4060 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); | 4055 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); |
@@ -4062,9 +4057,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
4062 | if (changed) | 4057 | if (changed) |
4063 | dev_disable_change(idev); | 4058 | dev_disable_change(idev); |
4064 | } | 4059 | } |
4065 | rcu_read_unlock(); | ||
4066 | } | 4060 | } |
4067 | read_unlock(&dev_base_lock); | 4061 | rcu_read_unlock(); |
4068 | } | 4062 | } |
4069 | 4063 | ||
4070 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | 4064 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index b6d058818673..12e69d364dd5 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -95,7 +95,8 @@ static __inline__ struct ipv6_pinfo *inet6_sk_generic(struct sock *sk) | |||
95 | return (struct ipv6_pinfo *)(((u8 *)sk) + offset); | 95 | return (struct ipv6_pinfo *)(((u8 *)sk) + offset); |
96 | } | 96 | } |
97 | 97 | ||
98 | static int inet6_create(struct net *net, struct socket *sock, int protocol) | 98 | static int inet6_create(struct net *net, struct socket *sock, int protocol, |
99 | int kern) | ||
99 | { | 100 | { |
100 | struct inet_sock *inet; | 101 | struct inet_sock *inet; |
101 | struct ipv6_pinfo *np; | 102 | struct ipv6_pinfo *np; |
@@ -158,7 +159,7 @@ lookup_protocol: | |||
158 | } | 159 | } |
159 | 160 | ||
160 | err = -EPERM; | 161 | err = -EPERM; |
161 | if (answer->capability > 0 && !capable(answer->capability)) | 162 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
162 | goto out_rcu_unlock; | 163 | goto out_rcu_unlock; |
163 | 164 | ||
164 | sock->ops = answer->ops; | 165 | sock->ops = answer->ops; |
@@ -314,6 +315,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
314 | if (addr_type != IPV6_ADDR_ANY) { | 315 | if (addr_type != IPV6_ADDR_ANY) { |
315 | struct net_device *dev = NULL; | 316 | struct net_device *dev = NULL; |
316 | 317 | ||
318 | rcu_read_lock(); | ||
317 | if (addr_type & IPV6_ADDR_LINKLOCAL) { | 319 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
318 | if (addr_len >= sizeof(struct sockaddr_in6) && | 320 | if (addr_len >= sizeof(struct sockaddr_in6) && |
319 | addr->sin6_scope_id) { | 321 | addr->sin6_scope_id) { |
@@ -326,12 +328,12 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
326 | /* Binding to link-local address requires an interface */ | 328 | /* Binding to link-local address requires an interface */ |
327 | if (!sk->sk_bound_dev_if) { | 329 | if (!sk->sk_bound_dev_if) { |
328 | err = -EINVAL; | 330 | err = -EINVAL; |
329 | goto out; | 331 | goto out_unlock; |
330 | } | 332 | } |
331 | dev = dev_get_by_index(net, sk->sk_bound_dev_if); | 333 | dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if); |
332 | if (!dev) { | 334 | if (!dev) { |
333 | err = -ENODEV; | 335 | err = -ENODEV; |
334 | goto out; | 336 | goto out_unlock; |
335 | } | 337 | } |
336 | } | 338 | } |
337 | 339 | ||
@@ -342,14 +344,11 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
342 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { | 344 | if (!(addr_type & IPV6_ADDR_MULTICAST)) { |
343 | if (!ipv6_chk_addr(net, &addr->sin6_addr, | 345 | if (!ipv6_chk_addr(net, &addr->sin6_addr, |
344 | dev, 0)) { | 346 | dev, 0)) { |
345 | if (dev) | ||
346 | dev_put(dev); | ||
347 | err = -EADDRNOTAVAIL; | 347 | err = -EADDRNOTAVAIL; |
348 | goto out; | 348 | goto out_unlock; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | if (dev) | 351 | rcu_read_unlock(); |
352 | dev_put(dev); | ||
353 | } | 352 | } |
354 | } | 353 | } |
355 | 354 | ||
@@ -381,6 +380,9 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
381 | out: | 380 | out: |
382 | release_sock(sk); | 381 | release_sock(sk); |
383 | return err; | 382 | return err; |
383 | out_unlock: | ||
384 | rcu_read_unlock(); | ||
385 | goto out; | ||
384 | } | 386 | } |
385 | 387 | ||
386 | EXPORT_SYMBOL(inet6_bind); | 388 | EXPORT_SYMBOL(inet6_bind); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 1ae58bec1de0..2f00ca83f049 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -404,13 +404,13 @@ int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | |||
404 | 404 | ||
405 | if (dev) | 405 | if (dev) |
406 | return ipv6_chk_acast_dev(dev, addr); | 406 | return ipv6_chk_acast_dev(dev, addr); |
407 | read_lock(&dev_base_lock); | 407 | rcu_read_lock(); |
408 | for_each_netdev(net, dev) | 408 | for_each_netdev_rcu(net, dev) |
409 | if (ipv6_chk_acast_dev(dev, addr)) { | 409 | if (ipv6_chk_acast_dev(dev, addr)) { |
410 | found = 1; | 410 | found = 1; |
411 | break; | 411 | break; |
412 | } | 412 | } |
413 | read_unlock(&dev_base_lock); | 413 | rcu_read_unlock(); |
414 | return found; | 414 | return found; |
415 | } | 415 | } |
416 | 416 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 9f70452a69e7..e6f9cdf780fe 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -537,12 +537,17 @@ int datagram_send_ctl(struct net *net, | |||
537 | 537 | ||
538 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); | 538 | addr_type = __ipv6_addr_type(&src_info->ipi6_addr); |
539 | 539 | ||
540 | rcu_read_lock(); | ||
540 | if (fl->oif) { | 541 | if (fl->oif) { |
541 | dev = dev_get_by_index(net, fl->oif); | 542 | dev = dev_get_by_index_rcu(net, fl->oif); |
542 | if (!dev) | 543 | if (!dev) { |
544 | rcu_read_unlock(); | ||
543 | return -ENODEV; | 545 | return -ENODEV; |
544 | } else if (addr_type & IPV6_ADDR_LINKLOCAL) | 546 | } |
547 | } else if (addr_type & IPV6_ADDR_LINKLOCAL) { | ||
548 | rcu_read_unlock(); | ||
545 | return -EINVAL; | 549 | return -EINVAL; |
550 | } | ||
546 | 551 | ||
547 | if (addr_type != IPV6_ADDR_ANY) { | 552 | if (addr_type != IPV6_ADDR_ANY) { |
548 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; | 553 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
@@ -553,8 +558,7 @@ int datagram_send_ctl(struct net *net, | |||
553 | ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr); | 558 | ipv6_addr_copy(&fl->fl6_src, &src_info->ipi6_addr); |
554 | } | 559 | } |
555 | 560 | ||
556 | if (dev) | 561 | rcu_read_unlock(); |
557 | dev_put(dev); | ||
558 | 562 | ||
559 | if (err) | 563 | if (err) |
560 | goto exit_f; | 564 | goto exit_f; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 6c1b5c98e818..1d614113a4ba 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -658,6 +658,7 @@ static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, | |||
658 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 658 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
659 | } | 659 | } |
660 | 660 | ||
661 | /* called with rcu_read_lock() */ | ||
661 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | 662 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) |
662 | { | 663 | { |
663 | struct ip6_tnl_parm *p = &t->parms; | 664 | struct ip6_tnl_parm *p = &t->parms; |
@@ -668,15 +669,13 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | |||
668 | struct net_device *ldev = NULL; | 669 | struct net_device *ldev = NULL; |
669 | 670 | ||
670 | if (p->link) | 671 | if (p->link) |
671 | ldev = dev_get_by_index(net, p->link); | 672 | ldev = dev_get_by_index_rcu(net, p->link); |
672 | 673 | ||
673 | if ((ipv6_addr_is_multicast(&p->laddr) || | 674 | if ((ipv6_addr_is_multicast(&p->laddr) || |
674 | likely(ipv6_chk_addr(net, &p->laddr, ldev, 0))) && | 675 | likely(ipv6_chk_addr(net, &p->laddr, ldev, 0))) && |
675 | likely(!ipv6_chk_addr(net, &p->raddr, NULL, 0))) | 676 | likely(!ipv6_chk_addr(net, &p->raddr, NULL, 0))) |
676 | ret = 1; | 677 | ret = 1; |
677 | 678 | ||
678 | if (ldev) | ||
679 | dev_put(ldev); | ||
680 | } | 679 | } |
681 | return ret; | 680 | return ret; |
682 | } | 681 | } |
@@ -804,8 +803,9 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
804 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | 803 | if (p->flags & IP6_TNL_F_CAP_XMIT) { |
805 | struct net_device *ldev = NULL; | 804 | struct net_device *ldev = NULL; |
806 | 805 | ||
806 | rcu_read_lock(); | ||
807 | if (p->link) | 807 | if (p->link) |
808 | ldev = dev_get_by_index(net, p->link); | 808 | ldev = dev_get_by_index_rcu(net, p->link); |
809 | 809 | ||
810 | if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0))) | 810 | if (unlikely(!ipv6_chk_addr(net, &p->laddr, ldev, 0))) |
811 | printk(KERN_WARNING | 811 | printk(KERN_WARNING |
@@ -819,8 +819,7 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
819 | p->name); | 819 | p->name); |
820 | else | 820 | else |
821 | ret = 1; | 821 | ret = 1; |
822 | if (ldev) | 822 | rcu_read_unlock(); |
823 | dev_put(ldev); | ||
824 | } | 823 | } |
825 | return ret; | 824 | return ret; |
826 | } | 825 | } |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index cb834ab7f071..926ce8eeffaf 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -249,7 +249,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
249 | 249 | ||
250 | /* Raw sockets are IPv6 only */ | 250 | /* Raw sockets are IPv6 only */ |
251 | if (addr_type == IPV6_ADDR_MAPPED) | 251 | if (addr_type == IPV6_ADDR_MAPPED) |
252 | return(-EADDRNOTAVAIL); | 252 | return -EADDRNOTAVAIL; |
253 | 253 | ||
254 | lock_sock(sk); | 254 | lock_sock(sk); |
255 | 255 | ||
@@ -257,6 +257,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
257 | if (sk->sk_state != TCP_CLOSE) | 257 | if (sk->sk_state != TCP_CLOSE) |
258 | goto out; | 258 | goto out; |
259 | 259 | ||
260 | rcu_read_lock(); | ||
260 | /* Check if the address belongs to the host. */ | 261 | /* Check if the address belongs to the host. */ |
261 | if (addr_type != IPV6_ADDR_ANY) { | 262 | if (addr_type != IPV6_ADDR_ANY) { |
262 | struct net_device *dev = NULL; | 263 | struct net_device *dev = NULL; |
@@ -272,13 +273,13 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
272 | 273 | ||
273 | /* Binding to link-local address requires an interface */ | 274 | /* Binding to link-local address requires an interface */ |
274 | if (!sk->sk_bound_dev_if) | 275 | if (!sk->sk_bound_dev_if) |
275 | goto out; | 276 | goto out_unlock; |
276 | 277 | ||
277 | dev = dev_get_by_index(sock_net(sk), sk->sk_bound_dev_if); | 278 | err = -ENODEV; |
278 | if (!dev) { | 279 | dev = dev_get_by_index_rcu(sock_net(sk), |
279 | err = -ENODEV; | 280 | sk->sk_bound_dev_if); |
280 | goto out; | 281 | if (!dev) |
281 | } | 282 | goto out_unlock; |
282 | } | 283 | } |
283 | 284 | ||
284 | /* ipv4 addr of the socket is invalid. Only the | 285 | /* ipv4 addr of the socket is invalid. Only the |
@@ -289,13 +290,9 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
289 | err = -EADDRNOTAVAIL; | 290 | err = -EADDRNOTAVAIL; |
290 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, | 291 | if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, |
291 | dev, 0)) { | 292 | dev, 0)) { |
292 | if (dev) | 293 | goto out_unlock; |
293 | dev_put(dev); | ||
294 | goto out; | ||
295 | } | 294 | } |
296 | } | 295 | } |
297 | if (dev) | ||
298 | dev_put(dev); | ||
299 | } | 296 | } |
300 | 297 | ||
301 | inet->inet_rcv_saddr = inet->inet_saddr = v4addr; | 298 | inet->inet_rcv_saddr = inet->inet_saddr = v4addr; |
@@ -303,6 +300,8 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
303 | if (!(addr_type & IPV6_ADDR_MULTICAST)) | 300 | if (!(addr_type & IPV6_ADDR_MULTICAST)) |
304 | ipv6_addr_copy(&np->saddr, &addr->sin6_addr); | 301 | ipv6_addr_copy(&np->saddr, &addr->sin6_addr); |
305 | err = 0; | 302 | err = 0; |
303 | out_unlock: | ||
304 | rcu_read_unlock(); | ||
306 | out: | 305 | out: |
307 | release_sock(sk); | 306 | release_sock(sk); |
308 | return err; | 307 | return err; |
@@ -1336,7 +1335,6 @@ static struct inet_protosw rawv6_protosw = { | |||
1336 | .protocol = IPPROTO_IP, /* wild card */ | 1335 | .protocol = IPPROTO_IP, /* wild card */ |
1337 | .prot = &rawv6_prot, | 1336 | .prot = &rawv6_prot, |
1338 | .ops = &inet6_sockraw_ops, | 1337 | .ops = &inet6_sockraw_ops, |
1339 | .capability = CAP_NET_RAW, | ||
1340 | .no_check = UDP_CSUM_DEFAULT, | 1338 | .no_check = UDP_CSUM_DEFAULT, |
1341 | .flags = INET_PROTOSW_REUSE, | 1339 | .flags = INET_PROTOSW_REUSE, |
1342 | }; | 1340 | }; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index da5bd0ed83df..dce699fb2672 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -208,18 +208,17 @@ static void ip6_frag_expire(unsigned long data) | |||
208 | fq_kill(fq); | 208 | fq_kill(fq); |
209 | 209 | ||
210 | net = container_of(fq->q.net, struct net, ipv6.frags); | 210 | net = container_of(fq->q.net, struct net, ipv6.frags); |
211 | dev = dev_get_by_index(net, fq->iif); | 211 | rcu_read_lock(); |
212 | dev = dev_get_by_index_rcu(net, fq->iif); | ||
212 | if (!dev) | 213 | if (!dev) |
213 | goto out; | 214 | goto out_rcu_unlock; |
214 | 215 | ||
215 | rcu_read_lock(); | ||
216 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | 216 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); |
217 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 217 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); |
218 | rcu_read_unlock(); | ||
219 | 218 | ||
220 | /* Don't send error if the first segment did not arrive. */ | 219 | /* Don't send error if the first segment did not arrive. */ |
221 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) | 220 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) |
222 | goto out; | 221 | goto out_rcu_unlock; |
223 | 222 | ||
224 | /* | 223 | /* |
225 | But use as source device on which LAST ARRIVED | 224 | But use as source device on which LAST ARRIVED |
@@ -228,9 +227,9 @@ static void ip6_frag_expire(unsigned long data) | |||
228 | */ | 227 | */ |
229 | fq->q.fragments->dev = dev; | 228 | fq->q.fragments->dev = dev; |
230 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); | 229 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0, dev); |
230 | out_rcu_unlock: | ||
231 | rcu_read_unlock(); | ||
231 | out: | 232 | out: |
232 | if (dev) | ||
233 | dev_put(dev); | ||
234 | spin_unlock(&fq->q.lock); | 233 | spin_unlock(&fq->q.lock); |
235 | fq_put(fq); | 234 | fq_put(fq); |
236 | } | 235 | } |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 34925f089e07..696a22f034e8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -2112,7 +2112,6 @@ static struct inet_protosw tcpv6_protosw = { | |||
2112 | .protocol = IPPROTO_TCP, | 2112 | .protocol = IPPROTO_TCP, |
2113 | .prot = &tcpv6_prot, | 2113 | .prot = &tcpv6_prot, |
2114 | .ops = &inet6_stream_ops, | 2114 | .ops = &inet6_stream_ops, |
2115 | .capability = -1, | ||
2116 | .no_check = 0, | 2115 | .no_check = 0, |
2117 | .flags = INET_PROTOSW_PERMANENT | | 2116 | .flags = INET_PROTOSW_PERMANENT | |
2118 | INET_PROTOSW_ICSK, | 2117 | INET_PROTOSW_ICSK, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d3b59d73f507..2915e1dad726 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -81,8 +81,30 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
81 | return 0; | 81 | return 0; |
82 | } | 82 | } |
83 | 83 | ||
84 | static unsigned int udp6_portaddr_hash(struct net *net, | ||
85 | const struct in6_addr *addr6, | ||
86 | unsigned int port) | ||
87 | { | ||
88 | unsigned int hash, mix = net_hash_mix(net); | ||
89 | |||
90 | if (ipv6_addr_any(addr6)) | ||
91 | hash = jhash_1word(0, mix); | ||
92 | else if (ipv6_addr_type(addr6) == IPV6_ADDR_MAPPED) | ||
93 | hash = jhash_1word(addr6->s6_addr32[3], mix); | ||
94 | else | ||
95 | hash = jhash2(addr6->s6_addr32, 4, mix); | ||
96 | |||
97 | return hash ^ port; | ||
98 | } | ||
99 | |||
100 | |||
84 | int udp_v6_get_port(struct sock *sk, unsigned short snum) | 101 | int udp_v6_get_port(struct sock *sk, unsigned short snum) |
85 | { | 102 | { |
103 | /* precompute partial secondary hash */ | ||
104 | udp_sk(sk)->udp_portaddr_hash = | ||
105 | udp6_portaddr_hash(sock_net(sk), | ||
106 | &inet6_sk(sk)->rcv_saddr, | ||
107 | 0); | ||
86 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); | 108 | return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal); |
87 | } | 109 | } |
88 | 110 | ||
@@ -94,7 +116,7 @@ static inline int compute_score(struct sock *sk, struct net *net, | |||
94 | { | 116 | { |
95 | int score = -1; | 117 | int score = -1; |
96 | 118 | ||
97 | if (net_eq(sock_net(sk), net) && sk->sk_hash == hnum && | 119 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && |
98 | sk->sk_family == PF_INET6) { | 120 | sk->sk_family == PF_INET6) { |
99 | struct ipv6_pinfo *np = inet6_sk(sk); | 121 | struct ipv6_pinfo *np = inet6_sk(sk); |
100 | struct inet_sock *inet = inet_sk(sk); | 122 | struct inet_sock *inet = inet_sk(sk); |
@@ -124,6 +146,88 @@ static inline int compute_score(struct sock *sk, struct net *net, | |||
124 | return score; | 146 | return score; |
125 | } | 147 | } |
126 | 148 | ||
149 | #define SCORE2_MAX (1 + 1 + 1) | ||
150 | static inline int compute_score2(struct sock *sk, struct net *net, | ||
151 | const struct in6_addr *saddr, __be16 sport, | ||
152 | const struct in6_addr *daddr, unsigned short hnum, | ||
153 | int dif) | ||
154 | { | ||
155 | int score = -1; | ||
156 | |||
157 | if (net_eq(sock_net(sk), net) && udp_sk(sk)->udp_port_hash == hnum && | ||
158 | sk->sk_family == PF_INET6) { | ||
159 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
160 | struct inet_sock *inet = inet_sk(sk); | ||
161 | |||
162 | if (!ipv6_addr_equal(&np->rcv_saddr, daddr)) | ||
163 | return -1; | ||
164 | score = 0; | ||
165 | if (inet->inet_dport) { | ||
166 | if (inet->inet_dport != sport) | ||
167 | return -1; | ||
168 | score++; | ||
169 | } | ||
170 | if (!ipv6_addr_any(&np->daddr)) { | ||
171 | if (!ipv6_addr_equal(&np->daddr, saddr)) | ||
172 | return -1; | ||
173 | score++; | ||
174 | } | ||
175 | if (sk->sk_bound_dev_if) { | ||
176 | if (sk->sk_bound_dev_if != dif) | ||
177 | return -1; | ||
178 | score++; | ||
179 | } | ||
180 | } | ||
181 | return score; | ||
182 | } | ||
183 | |||
184 | #define udp_portaddr_for_each_entry_rcu(__sk, node, list) \ | ||
185 | hlist_nulls_for_each_entry_rcu(__sk, node, list, __sk_common.skc_portaddr_node) | ||
186 | |||
187 | /* called with read_rcu_lock() */ | ||
188 | static struct sock *udp6_lib_lookup2(struct net *net, | ||
189 | const struct in6_addr *saddr, __be16 sport, | ||
190 | const struct in6_addr *daddr, unsigned int hnum, int dif, | ||
191 | struct udp_hslot *hslot2, unsigned int slot2) | ||
192 | { | ||
193 | struct sock *sk, *result; | ||
194 | struct hlist_nulls_node *node; | ||
195 | int score, badness; | ||
196 | |||
197 | begin: | ||
198 | result = NULL; | ||
199 | badness = -1; | ||
200 | udp_portaddr_for_each_entry_rcu(sk, node, &hslot2->head) { | ||
201 | score = compute_score2(sk, net, saddr, sport, | ||
202 | daddr, hnum, dif); | ||
203 | if (score > badness) { | ||
204 | result = sk; | ||
205 | badness = score; | ||
206 | if (score == SCORE2_MAX) | ||
207 | goto exact_match; | ||
208 | } | ||
209 | } | ||
210 | /* | ||
211 | * if the nulls value we got at the end of this lookup is | ||
212 | * not the expected one, we must restart lookup. | ||
213 | * We probably met an item that was moved to another chain. | ||
214 | */ | ||
215 | if (get_nulls_value(node) != slot2) | ||
216 | goto begin; | ||
217 | |||
218 | if (result) { | ||
219 | exact_match: | ||
220 | if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt))) | ||
221 | result = NULL; | ||
222 | else if (unlikely(compute_score2(result, net, saddr, sport, | ||
223 | daddr, hnum, dif) < badness)) { | ||
224 | sock_put(result); | ||
225 | goto begin; | ||
226 | } | ||
227 | } | ||
228 | return result; | ||
229 | } | ||
230 | |||
127 | static struct sock *__udp6_lib_lookup(struct net *net, | 231 | static struct sock *__udp6_lib_lookup(struct net *net, |
128 | struct in6_addr *saddr, __be16 sport, | 232 | struct in6_addr *saddr, __be16 sport, |
129 | struct in6_addr *daddr, __be16 dport, | 233 | struct in6_addr *daddr, __be16 dport, |
@@ -132,11 +236,35 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
132 | struct sock *sk, *result; | 236 | struct sock *sk, *result; |
133 | struct hlist_nulls_node *node; | 237 | struct hlist_nulls_node *node; |
134 | unsigned short hnum = ntohs(dport); | 238 | unsigned short hnum = ntohs(dport); |
135 | unsigned int hash = udp_hashfn(net, hnum, udptable->mask); | 239 | unsigned int hash2, slot2, slot = udp_hashfn(net, hnum, udptable->mask); |
136 | struct udp_hslot *hslot = &udptable->hash[hash]; | 240 | struct udp_hslot *hslot2, *hslot = &udptable->hash[slot]; |
137 | int score, badness; | 241 | int score, badness; |
138 | 242 | ||
139 | rcu_read_lock(); | 243 | rcu_read_lock(); |
244 | if (hslot->count > 10) { | ||
245 | hash2 = udp6_portaddr_hash(net, daddr, hnum); | ||
246 | slot2 = hash2 & udptable->mask; | ||
247 | hslot2 = &udptable->hash2[slot2]; | ||
248 | if (hslot->count < hslot2->count) | ||
249 | goto begin; | ||
250 | |||
251 | result = udp6_lib_lookup2(net, saddr, sport, | ||
252 | daddr, hnum, dif, | ||
253 | hslot2, slot2); | ||
254 | if (!result) { | ||
255 | hash2 = udp6_portaddr_hash(net, &in6addr_any, hnum); | ||
256 | slot2 = hash2 & udptable->mask; | ||
257 | hslot2 = &udptable->hash2[slot2]; | ||
258 | if (hslot->count < hslot2->count) | ||
259 | goto begin; | ||
260 | |||
261 | result = udp6_lib_lookup2(net, &in6addr_any, sport, | ||
262 | daddr, hnum, dif, | ||
263 | hslot2, slot2); | ||
264 | } | ||
265 | rcu_read_unlock(); | ||
266 | return result; | ||
267 | } | ||
140 | begin: | 268 | begin: |
141 | result = NULL; | 269 | result = NULL; |
142 | badness = -1; | 270 | badness = -1; |
@@ -152,7 +280,7 @@ begin: | |||
152 | * not the expected one, we must restart lookup. | 280 | * not the expected one, we must restart lookup. |
153 | * We probably met an item that was moved to another chain. | 281 | * We probably met an item that was moved to another chain. |
154 | */ | 282 | */ |
155 | if (get_nulls_value(node) != hash) | 283 | if (get_nulls_value(node) != slot) |
156 | goto begin; | 284 | goto begin; |
157 | 285 | ||
158 | if (result) { | 286 | if (result) { |
@@ -288,9 +416,7 @@ try_again: | |||
288 | err = ulen; | 416 | err = ulen; |
289 | 417 | ||
290 | out_free: | 418 | out_free: |
291 | lock_sock(sk); | 419 | skb_free_datagram_locked(sk, skb); |
292 | skb_free_datagram(sk, skb); | ||
293 | release_sock(sk); | ||
294 | out: | 420 | out: |
295 | return err; | 421 | return err; |
296 | 422 | ||
@@ -417,7 +543,8 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | |||
417 | if (!net_eq(sock_net(s), net)) | 543 | if (!net_eq(sock_net(s), net)) |
418 | continue; | 544 | continue; |
419 | 545 | ||
420 | if (s->sk_hash == num && s->sk_family == PF_INET6) { | 546 | if (udp_sk(s)->udp_port_hash == num && |
547 | s->sk_family == PF_INET6) { | ||
421 | struct ipv6_pinfo *np = inet6_sk(s); | 548 | struct ipv6_pinfo *np = inet6_sk(s); |
422 | if (inet->inet_dport) { | 549 | if (inet->inet_dport) { |
423 | if (inet->inet_dport != rmt_port) | 550 | if (inet->inet_dport != rmt_port) |
@@ -442,6 +569,33 @@ static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | |||
442 | return NULL; | 569 | return NULL; |
443 | } | 570 | } |
444 | 571 | ||
572 | static void flush_stack(struct sock **stack, unsigned int count, | ||
573 | struct sk_buff *skb, unsigned int final) | ||
574 | { | ||
575 | unsigned int i; | ||
576 | struct sock *sk; | ||
577 | struct sk_buff *skb1; | ||
578 | |||
579 | for (i = 0; i < count; i++) { | ||
580 | skb1 = (i == final) ? skb : skb_clone(skb, GFP_ATOMIC); | ||
581 | |||
582 | sk = stack[i]; | ||
583 | if (skb1) { | ||
584 | bh_lock_sock(sk); | ||
585 | if (!sock_owned_by_user(sk)) | ||
586 | udpv6_queue_rcv_skb(sk, skb1); | ||
587 | else | ||
588 | sk_add_backlog(sk, skb1); | ||
589 | bh_unlock_sock(sk); | ||
590 | } else { | ||
591 | atomic_inc(&sk->sk_drops); | ||
592 | UDP6_INC_STATS_BH(sock_net(sk), | ||
593 | UDP_MIB_RCVBUFERRORS, IS_UDPLITE(sk)); | ||
594 | UDP6_INC_STATS_BH(sock_net(sk), | ||
595 | UDP_MIB_INERRORS, IS_UDPLITE(sk)); | ||
596 | } | ||
597 | } | ||
598 | } | ||
445 | /* | 599 | /* |
446 | * Note: called only from the BH handler context, | 600 | * Note: called only from the BH handler context, |
447 | * so we don't need to lock the hashes. | 601 | * so we don't need to lock the hashes. |
@@ -450,41 +604,43 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
450 | struct in6_addr *saddr, struct in6_addr *daddr, | 604 | struct in6_addr *saddr, struct in6_addr *daddr, |
451 | struct udp_table *udptable) | 605 | struct udp_table *udptable) |
452 | { | 606 | { |
453 | struct sock *sk, *sk2; | 607 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
454 | const struct udphdr *uh = udp_hdr(skb); | 608 | const struct udphdr *uh = udp_hdr(skb); |
455 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); | 609 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); |
456 | int dif; | 610 | int dif; |
611 | unsigned int i, count = 0; | ||
457 | 612 | ||
458 | spin_lock(&hslot->lock); | 613 | spin_lock(&hslot->lock); |
459 | sk = sk_nulls_head(&hslot->head); | 614 | sk = sk_nulls_head(&hslot->head); |
460 | dif = inet6_iif(skb); | 615 | dif = inet6_iif(skb); |
461 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 616 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); |
462 | if (!sk) { | 617 | while (sk) { |
463 | kfree_skb(skb); | 618 | stack[count++] = sk; |
464 | goto out; | 619 | sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, |
465 | } | 620 | uh->source, saddr, dif); |
466 | 621 | if (unlikely(count == ARRAY_SIZE(stack))) { | |
467 | sk2 = sk; | 622 | if (!sk) |
468 | while ((sk2 = udp_v6_mcast_next(net, sk_nulls_next(sk2), uh->dest, daddr, | 623 | break; |
469 | uh->source, saddr, dif))) { | 624 | flush_stack(stack, count, skb, ~0); |
470 | struct sk_buff *buff = skb_clone(skb, GFP_ATOMIC); | 625 | count = 0; |
471 | if (buff) { | ||
472 | bh_lock_sock(sk2); | ||
473 | if (!sock_owned_by_user(sk2)) | ||
474 | udpv6_queue_rcv_skb(sk2, buff); | ||
475 | else | ||
476 | sk_add_backlog(sk2, buff); | ||
477 | bh_unlock_sock(sk2); | ||
478 | } | 626 | } |
479 | } | 627 | } |
480 | bh_lock_sock(sk); | 628 | /* |
481 | if (!sock_owned_by_user(sk)) | 629 | * before releasing the lock, we must take reference on sockets |
482 | udpv6_queue_rcv_skb(sk, skb); | 630 | */ |
483 | else | 631 | for (i = 0; i < count; i++) |
484 | sk_add_backlog(sk, skb); | 632 | sock_hold(stack[i]); |
485 | bh_unlock_sock(sk); | 633 | |
486 | out: | ||
487 | spin_unlock(&hslot->lock); | 634 | spin_unlock(&hslot->lock); |
635 | |||
636 | if (count) { | ||
637 | flush_stack(stack, count, skb, count - 1); | ||
638 | |||
639 | for (i = 0; i < count; i++) | ||
640 | sock_put(stack[i]); | ||
641 | } else { | ||
642 | kfree_skb(skb); | ||
643 | } | ||
488 | return 0; | 644 | return 0; |
489 | } | 645 | } |
490 | 646 | ||
@@ -1286,7 +1442,6 @@ static struct inet_protosw udpv6_protosw = { | |||
1286 | .protocol = IPPROTO_UDP, | 1442 | .protocol = IPPROTO_UDP, |
1287 | .prot = &udpv6_prot, | 1443 | .prot = &udpv6_prot, |
1288 | .ops = &inet6_dgram_ops, | 1444 | .ops = &inet6_dgram_ops, |
1289 | .capability =-1, | ||
1290 | .no_check = UDP_CSUM_DEFAULT, | 1445 | .no_check = UDP_CSUM_DEFAULT, |
1291 | .flags = INET_PROTOSW_PERMANENT, | 1446 | .flags = INET_PROTOSW_PERMANENT, |
1292 | }; | 1447 | }; |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index d737a27ee010..6ea6938919e6 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
@@ -62,7 +62,6 @@ static struct inet_protosw udplite6_protosw = { | |||
62 | .protocol = IPPROTO_UDPLITE, | 62 | .protocol = IPPROTO_UDPLITE, |
63 | .prot = &udplitev6_prot, | 63 | .prot = &udplitev6_prot, |
64 | .ops = &inet6_dgram_ops, | 64 | .ops = &inet6_dgram_ops, |
65 | .capability = -1, | ||
66 | .no_check = 0, | 65 | .no_check = 0, |
67 | .flags = INET_PROTOSW_PERMANENT, | 66 | .flags = INET_PROTOSW_PERMANENT, |
68 | }; | 67 | }; |
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 6481ee4bdf72..975c5a366e55 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1298,6 +1298,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, | |||
1298 | int opt; | 1298 | int opt; |
1299 | int rc = -EINVAL; | 1299 | int rc = -EINVAL; |
1300 | 1300 | ||
1301 | lock_kernel(); | ||
1301 | if (optlen != sizeof(int)) | 1302 | if (optlen != sizeof(int)) |
1302 | goto out; | 1303 | goto out; |
1303 | 1304 | ||
@@ -1312,6 +1313,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname, | |||
1312 | ipx_sk(sk)->type = opt; | 1313 | ipx_sk(sk)->type = opt; |
1313 | rc = 0; | 1314 | rc = 0; |
1314 | out: | 1315 | out: |
1316 | unlock_kernel(); | ||
1315 | return rc; | 1317 | return rc; |
1316 | } | 1318 | } |
1317 | 1319 | ||
@@ -1323,6 +1325,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname, | |||
1323 | int len; | 1325 | int len; |
1324 | int rc = -ENOPROTOOPT; | 1326 | int rc = -ENOPROTOOPT; |
1325 | 1327 | ||
1328 | lock_kernel(); | ||
1326 | if (!(level == SOL_IPX && optname == IPX_TYPE)) | 1329 | if (!(level == SOL_IPX && optname == IPX_TYPE)) |
1327 | goto out; | 1330 | goto out; |
1328 | 1331 | ||
@@ -1343,6 +1346,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname, | |||
1343 | 1346 | ||
1344 | rc = 0; | 1347 | rc = 0; |
1345 | out: | 1348 | out: |
1349 | unlock_kernel(); | ||
1346 | return rc; | 1350 | return rc; |
1347 | } | 1351 | } |
1348 | 1352 | ||
@@ -1352,7 +1356,8 @@ static struct proto ipx_proto = { | |||
1352 | .obj_size = sizeof(struct ipx_sock), | 1356 | .obj_size = sizeof(struct ipx_sock), |
1353 | }; | 1357 | }; |
1354 | 1358 | ||
1355 | static int ipx_create(struct net *net, struct socket *sock, int protocol) | 1359 | static int ipx_create(struct net *net, struct socket *sock, int protocol, |
1360 | int kern) | ||
1356 | { | 1361 | { |
1357 | int rc = -ESOCKTNOSUPPORT; | 1362 | int rc = -ESOCKTNOSUPPORT; |
1358 | struct sock *sk; | 1363 | struct sock *sk; |
@@ -1390,6 +1395,7 @@ static int ipx_release(struct socket *sock) | |||
1390 | if (!sk) | 1395 | if (!sk) |
1391 | goto out; | 1396 | goto out; |
1392 | 1397 | ||
1398 | lock_kernel(); | ||
1393 | if (!sock_flag(sk, SOCK_DEAD)) | 1399 | if (!sock_flag(sk, SOCK_DEAD)) |
1394 | sk->sk_state_change(sk); | 1400 | sk->sk_state_change(sk); |
1395 | 1401 | ||
@@ -1397,6 +1403,7 @@ static int ipx_release(struct socket *sock) | |||
1397 | sock->sk = NULL; | 1403 | sock->sk = NULL; |
1398 | sk_refcnt_debug_release(sk); | 1404 | sk_refcnt_debug_release(sk); |
1399 | ipx_destroy_socket(sk); | 1405 | ipx_destroy_socket(sk); |
1406 | unlock_kernel(); | ||
1400 | out: | 1407 | out: |
1401 | return 0; | 1408 | return 0; |
1402 | } | 1409 | } |
@@ -1424,7 +1431,8 @@ static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc) | |||
1424 | return htons(socketNum); | 1431 | return htons(socketNum); |
1425 | } | 1432 | } |
1426 | 1433 | ||
1427 | static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | 1434 | static int __ipx_bind(struct socket *sock, |
1435 | struct sockaddr *uaddr, int addr_len) | ||
1428 | { | 1436 | { |
1429 | struct sock *sk = sock->sk; | 1437 | struct sock *sk = sock->sk; |
1430 | struct ipx_sock *ipxs = ipx_sk(sk); | 1438 | struct ipx_sock *ipxs = ipx_sk(sk); |
@@ -1519,6 +1527,17 @@ out: | |||
1519 | return rc; | 1527 | return rc; |
1520 | } | 1528 | } |
1521 | 1529 | ||
1530 | static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | ||
1531 | { | ||
1532 | int rc; | ||
1533 | |||
1534 | lock_kernel(); | ||
1535 | rc = __ipx_bind(sock, uaddr, addr_len); | ||
1536 | unlock_kernel(); | ||
1537 | |||
1538 | return rc; | ||
1539 | } | ||
1540 | |||
1522 | static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, | 1541 | static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, |
1523 | int addr_len, int flags) | 1542 | int addr_len, int flags) |
1524 | { | 1543 | { |
@@ -1531,6 +1550,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1531 | sk->sk_state = TCP_CLOSE; | 1550 | sk->sk_state = TCP_CLOSE; |
1532 | sock->state = SS_UNCONNECTED; | 1551 | sock->state = SS_UNCONNECTED; |
1533 | 1552 | ||
1553 | lock_kernel(); | ||
1534 | if (addr_len != sizeof(*addr)) | 1554 | if (addr_len != sizeof(*addr)) |
1535 | goto out; | 1555 | goto out; |
1536 | addr = (struct sockaddr_ipx *)uaddr; | 1556 | addr = (struct sockaddr_ipx *)uaddr; |
@@ -1550,7 +1570,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1550 | IPX_NODE_LEN); | 1570 | IPX_NODE_LEN); |
1551 | #endif /* CONFIG_IPX_INTERN */ | 1571 | #endif /* CONFIG_IPX_INTERN */ |
1552 | 1572 | ||
1553 | rc = ipx_bind(sock, (struct sockaddr *)&uaddr, | 1573 | rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, |
1554 | sizeof(struct sockaddr_ipx)); | 1574 | sizeof(struct sockaddr_ipx)); |
1555 | if (rc) | 1575 | if (rc) |
1556 | goto out; | 1576 | goto out; |
@@ -1577,6 +1597,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1577 | ipxrtr_put(rt); | 1597 | ipxrtr_put(rt); |
1578 | rc = 0; | 1598 | rc = 0; |
1579 | out: | 1599 | out: |
1600 | unlock_kernel(); | ||
1580 | return rc; | 1601 | return rc; |
1581 | } | 1602 | } |
1582 | 1603 | ||
@@ -1592,6 +1613,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1592 | 1613 | ||
1593 | *uaddr_len = sizeof(struct sockaddr_ipx); | 1614 | *uaddr_len = sizeof(struct sockaddr_ipx); |
1594 | 1615 | ||
1616 | lock_kernel(); | ||
1595 | if (peer) { | 1617 | if (peer) { |
1596 | rc = -ENOTCONN; | 1618 | rc = -ENOTCONN; |
1597 | if (sk->sk_state != TCP_ESTABLISHED) | 1619 | if (sk->sk_state != TCP_ESTABLISHED) |
@@ -1626,6 +1648,19 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1626 | 1648 | ||
1627 | rc = 0; | 1649 | rc = 0; |
1628 | out: | 1650 | out: |
1651 | unlock_kernel(); | ||
1652 | return rc; | ||
1653 | } | ||
1654 | |||
1655 | static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock, | ||
1656 | poll_table *wait) | ||
1657 | { | ||
1658 | int rc; | ||
1659 | |||
1660 | lock_kernel(); | ||
1661 | rc = datagram_poll(file, sock, wait); | ||
1662 | unlock_kernel(); | ||
1663 | |||
1629 | return rc; | 1664 | return rc; |
1630 | } | 1665 | } |
1631 | 1666 | ||
@@ -1700,6 +1735,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1700 | int rc = -EINVAL; | 1735 | int rc = -EINVAL; |
1701 | int flags = msg->msg_flags; | 1736 | int flags = msg->msg_flags; |
1702 | 1737 | ||
1738 | lock_kernel(); | ||
1703 | /* Socket gets bound below anyway */ | 1739 | /* Socket gets bound below anyway */ |
1704 | /* if (sk->sk_zapped) | 1740 | /* if (sk->sk_zapped) |
1705 | return -EIO; */ /* Socket not bound */ | 1741 | return -EIO; */ /* Socket not bound */ |
@@ -1723,7 +1759,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1723 | memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, | 1759 | memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, |
1724 | IPX_NODE_LEN); | 1760 | IPX_NODE_LEN); |
1725 | #endif | 1761 | #endif |
1726 | rc = ipx_bind(sock, (struct sockaddr *)&uaddr, | 1762 | rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, |
1727 | sizeof(struct sockaddr_ipx)); | 1763 | sizeof(struct sockaddr_ipx)); |
1728 | if (rc) | 1764 | if (rc) |
1729 | goto out; | 1765 | goto out; |
@@ -1751,6 +1787,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1751 | if (rc >= 0) | 1787 | if (rc >= 0) |
1752 | rc = len; | 1788 | rc = len; |
1753 | out: | 1789 | out: |
1790 | unlock_kernel(); | ||
1754 | return rc; | 1791 | return rc; |
1755 | } | 1792 | } |
1756 | 1793 | ||
@@ -1765,6 +1802,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1765 | struct sk_buff *skb; | 1802 | struct sk_buff *skb; |
1766 | int copied, rc; | 1803 | int copied, rc; |
1767 | 1804 | ||
1805 | lock_kernel(); | ||
1768 | /* put the autobinding in */ | 1806 | /* put the autobinding in */ |
1769 | if (!ipxs->port) { | 1807 | if (!ipxs->port) { |
1770 | struct sockaddr_ipx uaddr; | 1808 | struct sockaddr_ipx uaddr; |
@@ -1779,7 +1817,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1779 | memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); | 1817 | memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN); |
1780 | #endif /* CONFIG_IPX_INTERN */ | 1818 | #endif /* CONFIG_IPX_INTERN */ |
1781 | 1819 | ||
1782 | rc = ipx_bind(sock, (struct sockaddr *)&uaddr, | 1820 | rc = __ipx_bind(sock, (struct sockaddr *)&uaddr, |
1783 | sizeof(struct sockaddr_ipx)); | 1821 | sizeof(struct sockaddr_ipx)); |
1784 | if (rc) | 1822 | if (rc) |
1785 | goto out; | 1823 | goto out; |
@@ -1823,6 +1861,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1823 | out_free: | 1861 | out_free: |
1824 | skb_free_datagram(sk, skb); | 1862 | skb_free_datagram(sk, skb); |
1825 | out: | 1863 | out: |
1864 | unlock_kernel(); | ||
1826 | return rc; | 1865 | return rc; |
1827 | } | 1866 | } |
1828 | 1867 | ||
@@ -1834,6 +1873,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1834 | struct sock *sk = sock->sk; | 1873 | struct sock *sk = sock->sk; |
1835 | void __user *argp = (void __user *)arg; | 1874 | void __user *argp = (void __user *)arg; |
1836 | 1875 | ||
1876 | lock_kernel(); | ||
1837 | switch (cmd) { | 1877 | switch (cmd) { |
1838 | case TIOCOUTQ: | 1878 | case TIOCOUTQ: |
1839 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1879 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
@@ -1896,6 +1936,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1896 | rc = -ENOIOCTLCMD; | 1936 | rc = -ENOIOCTLCMD; |
1897 | break; | 1937 | break; |
1898 | } | 1938 | } |
1939 | unlock_kernel(); | ||
1899 | 1940 | ||
1900 | return rc; | 1941 | return rc; |
1901 | } | 1942 | } |
@@ -1933,7 +1974,7 @@ static const struct net_proto_family ipx_family_ops = { | |||
1933 | .owner = THIS_MODULE, | 1974 | .owner = THIS_MODULE, |
1934 | }; | 1975 | }; |
1935 | 1976 | ||
1936 | static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { | 1977 | static const struct proto_ops ipx_dgram_ops = { |
1937 | .family = PF_IPX, | 1978 | .family = PF_IPX, |
1938 | .owner = THIS_MODULE, | 1979 | .owner = THIS_MODULE, |
1939 | .release = ipx_release, | 1980 | .release = ipx_release, |
@@ -1942,7 +1983,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { | |||
1942 | .socketpair = sock_no_socketpair, | 1983 | .socketpair = sock_no_socketpair, |
1943 | .accept = sock_no_accept, | 1984 | .accept = sock_no_accept, |
1944 | .getname = ipx_getname, | 1985 | .getname = ipx_getname, |
1945 | .poll = datagram_poll, | 1986 | .poll = ipx_datagram_poll, |
1946 | .ioctl = ipx_ioctl, | 1987 | .ioctl = ipx_ioctl, |
1947 | #ifdef CONFIG_COMPAT | 1988 | #ifdef CONFIG_COMPAT |
1948 | .compat_ioctl = ipx_compat_ioctl, | 1989 | .compat_ioctl = ipx_compat_ioctl, |
@@ -1957,8 +1998,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { | |||
1957 | .sendpage = sock_no_sendpage, | 1998 | .sendpage = sock_no_sendpage, |
1958 | }; | 1999 | }; |
1959 | 2000 | ||
1960 | SOCKOPS_WRAP(ipx_dgram, PF_IPX); | ||
1961 | |||
1962 | static struct packet_type ipx_8023_packet_type __read_mostly = { | 2001 | static struct packet_type ipx_8023_packet_type __read_mostly = { |
1963 | .type = cpu_to_be16(ETH_P_802_3), | 2002 | .type = cpu_to_be16(ETH_P_802_3), |
1964 | .func = ipx_rcv, | 2003 | .func = ipx_rcv, |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 9429e4002bca..10093aab6173 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -61,7 +61,7 @@ | |||
61 | 61 | ||
62 | #include <net/irda/af_irda.h> | 62 | #include <net/irda/af_irda.h> |
63 | 63 | ||
64 | static int irda_create(struct net *net, struct socket *sock, int protocol); | 64 | static int irda_create(struct net *net, struct socket *sock, int protocol, int kern); |
65 | 65 | ||
66 | static const struct proto_ops irda_stream_ops; | 66 | static const struct proto_ops irda_stream_ops; |
67 | static const struct proto_ops irda_seqpacket_ops; | 67 | static const struct proto_ops irda_seqpacket_ops; |
@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
714 | struct sockaddr_irda saddr; | 714 | struct sockaddr_irda saddr; |
715 | struct sock *sk = sock->sk; | 715 | struct sock *sk = sock->sk; |
716 | struct irda_sock *self = irda_sk(sk); | 716 | struct irda_sock *self = irda_sk(sk); |
717 | int err; | ||
717 | 718 | ||
719 | lock_kernel(); | ||
718 | memset(&saddr, 0, sizeof(saddr)); | 720 | memset(&saddr, 0, sizeof(saddr)); |
719 | if (peer) { | 721 | if (peer) { |
722 | err = -ENOTCONN; | ||
720 | if (sk->sk_state != TCP_ESTABLISHED) | 723 | if (sk->sk_state != TCP_ESTABLISHED) |
721 | return -ENOTCONN; | 724 | goto out; |
722 | 725 | ||
723 | saddr.sir_family = AF_IRDA; | 726 | saddr.sir_family = AF_IRDA; |
724 | saddr.sir_lsap_sel = self->dtsap_sel; | 727 | saddr.sir_lsap_sel = self->dtsap_sel; |
@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
735 | /* uaddr_len come to us uninitialised */ | 738 | /* uaddr_len come to us uninitialised */ |
736 | *uaddr_len = sizeof (struct sockaddr_irda); | 739 | *uaddr_len = sizeof (struct sockaddr_irda); |
737 | memcpy(uaddr, &saddr, *uaddr_len); | 740 | memcpy(uaddr, &saddr, *uaddr_len); |
738 | 741 | err = 0; | |
739 | return 0; | 742 | out: |
743 | unlock_kernel(); | ||
744 | return err; | ||
740 | } | 745 | } |
741 | 746 | ||
742 | /* | 747 | /* |
@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, | |||
748 | static int irda_listen(struct socket *sock, int backlog) | 753 | static int irda_listen(struct socket *sock, int backlog) |
749 | { | 754 | { |
750 | struct sock *sk = sock->sk; | 755 | struct sock *sk = sock->sk; |
756 | int err = -EOPNOTSUPP; | ||
751 | 757 | ||
752 | IRDA_DEBUG(2, "%s()\n", __func__); | 758 | IRDA_DEBUG(2, "%s()\n", __func__); |
753 | 759 | ||
760 | lock_kernel(); | ||
754 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && | 761 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && |
755 | (sk->sk_type != SOCK_DGRAM)) | 762 | (sk->sk_type != SOCK_DGRAM)) |
756 | return -EOPNOTSUPP; | 763 | goto out; |
757 | 764 | ||
758 | if (sk->sk_state != TCP_LISTEN) { | 765 | if (sk->sk_state != TCP_LISTEN) { |
759 | sk->sk_max_ack_backlog = backlog; | 766 | sk->sk_max_ack_backlog = backlog; |
760 | sk->sk_state = TCP_LISTEN; | 767 | sk->sk_state = TCP_LISTEN; |
761 | 768 | ||
762 | return 0; | 769 | err = 0; |
763 | } | 770 | } |
771 | out: | ||
772 | unlock_kernel(); | ||
764 | 773 | ||
765 | return -EOPNOTSUPP; | 774 | return err; |
766 | } | 775 | } |
767 | 776 | ||
768 | /* | 777 | /* |
@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
783 | if (addr_len != sizeof(struct sockaddr_irda)) | 792 | if (addr_len != sizeof(struct sockaddr_irda)) |
784 | return -EINVAL; | 793 | return -EINVAL; |
785 | 794 | ||
795 | lock_kernel(); | ||
786 | #ifdef CONFIG_IRDA_ULTRA | 796 | #ifdef CONFIG_IRDA_ULTRA |
787 | /* Special care for Ultra sockets */ | 797 | /* Special care for Ultra sockets */ |
788 | if ((sk->sk_type == SOCK_DGRAM) && | 798 | if ((sk->sk_type == SOCK_DGRAM) && |
789 | (sk->sk_protocol == IRDAPROTO_ULTRA)) { | 799 | (sk->sk_protocol == IRDAPROTO_ULTRA)) { |
790 | self->pid = addr->sir_lsap_sel; | 800 | self->pid = addr->sir_lsap_sel; |
801 | err = -EOPNOTSUPP; | ||
791 | if (self->pid & 0x80) { | 802 | if (self->pid & 0x80) { |
792 | IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); | 803 | IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); |
793 | return -EOPNOTSUPP; | 804 | goto out; |
794 | } | 805 | } |
795 | err = irda_open_lsap(self, self->pid); | 806 | err = irda_open_lsap(self, self->pid); |
796 | if (err < 0) | 807 | if (err < 0) |
797 | return err; | 808 | goto out; |
798 | 809 | ||
799 | /* Pretend we are connected */ | 810 | /* Pretend we are connected */ |
800 | sock->state = SS_CONNECTED; | 811 | sock->state = SS_CONNECTED; |
801 | sk->sk_state = TCP_ESTABLISHED; | 812 | sk->sk_state = TCP_ESTABLISHED; |
813 | err = 0; | ||
802 | 814 | ||
803 | return 0; | 815 | goto out; |
804 | } | 816 | } |
805 | #endif /* CONFIG_IRDA_ULTRA */ | 817 | #endif /* CONFIG_IRDA_ULTRA */ |
806 | 818 | ||
807 | self->ias_obj = irias_new_object(addr->sir_name, jiffies); | 819 | self->ias_obj = irias_new_object(addr->sir_name, jiffies); |
820 | err = -ENOMEM; | ||
808 | if (self->ias_obj == NULL) | 821 | if (self->ias_obj == NULL) |
809 | return -ENOMEM; | 822 | goto out; |
810 | 823 | ||
811 | err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); | 824 | err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name); |
812 | if (err < 0) { | 825 | if (err < 0) { |
813 | kfree(self->ias_obj->name); | 826 | kfree(self->ias_obj->name); |
814 | kfree(self->ias_obj); | 827 | kfree(self->ias_obj); |
815 | return err; | 828 | goto out; |
816 | } | 829 | } |
817 | 830 | ||
818 | /* Register with LM-IAS */ | 831 | /* Register with LM-IAS */ |
@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
820 | self->stsap_sel, IAS_KERNEL_ATTR); | 833 | self->stsap_sel, IAS_KERNEL_ATTR); |
821 | irias_insert_object(self->ias_obj); | 834 | irias_insert_object(self->ias_obj); |
822 | 835 | ||
823 | return 0; | 836 | err = 0; |
837 | out: | ||
838 | unlock_kernel(); | ||
839 | return err; | ||
824 | } | 840 | } |
825 | 841 | ||
826 | /* | 842 | /* |
@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
839 | 855 | ||
840 | IRDA_DEBUG(2, "%s()\n", __func__); | 856 | IRDA_DEBUG(2, "%s()\n", __func__); |
841 | 857 | ||
842 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol); | 858 | lock_kernel(); |
859 | err = irda_create(sock_net(sk), newsock, sk->sk_protocol, 0); | ||
843 | if (err) | 860 | if (err) |
844 | return err; | 861 | goto out; |
845 | 862 | ||
863 | err = -EINVAL; | ||
846 | if (sock->state != SS_UNCONNECTED) | 864 | if (sock->state != SS_UNCONNECTED) |
847 | return -EINVAL; | 865 | goto out; |
848 | 866 | ||
849 | if ((sk = sock->sk) == NULL) | 867 | if ((sk = sock->sk) == NULL) |
850 | return -EINVAL; | 868 | goto out; |
851 | 869 | ||
870 | err = -EOPNOTSUPP; | ||
852 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && | 871 | if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) && |
853 | (sk->sk_type != SOCK_DGRAM)) | 872 | (sk->sk_type != SOCK_DGRAM)) |
854 | return -EOPNOTSUPP; | 873 | goto out; |
855 | 874 | ||
875 | err = -EINVAL; | ||
856 | if (sk->sk_state != TCP_LISTEN) | 876 | if (sk->sk_state != TCP_LISTEN) |
857 | return -EINVAL; | 877 | goto out; |
858 | 878 | ||
859 | /* | 879 | /* |
860 | * The read queue this time is holding sockets ready to use | 880 | * The read queue this time is holding sockets ready to use |
@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
875 | break; | 895 | break; |
876 | 896 | ||
877 | /* Non blocking operation */ | 897 | /* Non blocking operation */ |
898 | err = -EWOULDBLOCK; | ||
878 | if (flags & O_NONBLOCK) | 899 | if (flags & O_NONBLOCK) |
879 | return -EWOULDBLOCK; | 900 | goto out; |
880 | 901 | ||
881 | err = wait_event_interruptible(*(sk->sk_sleep), | 902 | err = wait_event_interruptible(*(sk->sk_sleep), |
882 | skb_peek(&sk->sk_receive_queue)); | 903 | skb_peek(&sk->sk_receive_queue)); |
883 | if (err) | 904 | if (err) |
884 | return err; | 905 | goto out; |
885 | } | 906 | } |
886 | 907 | ||
887 | newsk = newsock->sk; | 908 | newsk = newsock->sk; |
909 | err = -EIO; | ||
888 | if (newsk == NULL) | 910 | if (newsk == NULL) |
889 | return -EIO; | 911 | goto out; |
890 | 912 | ||
891 | newsk->sk_state = TCP_ESTABLISHED; | 913 | newsk->sk_state = TCP_ESTABLISHED; |
892 | 914 | ||
@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
894 | 916 | ||
895 | /* Now attach up the new socket */ | 917 | /* Now attach up the new socket */ |
896 | new->tsap = irttp_dup(self->tsap, new); | 918 | new->tsap = irttp_dup(self->tsap, new); |
919 | err = -EPERM; /* value does not seem to make sense. -arnd */ | ||
897 | if (!new->tsap) { | 920 | if (!new->tsap) { |
898 | IRDA_DEBUG(0, "%s(), dup failed!\n", __func__); | 921 | IRDA_DEBUG(0, "%s(), dup failed!\n", __func__); |
899 | kfree_skb(skb); | 922 | kfree_skb(skb); |
900 | return -1; | 923 | goto out; |
901 | } | 924 | } |
902 | 925 | ||
903 | new->stsap_sel = new->tsap->stsap_sel; | 926 | new->stsap_sel = new->tsap->stsap_sel; |
@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) | |||
921 | newsock->state = SS_CONNECTED; | 944 | newsock->state = SS_CONNECTED; |
922 | 945 | ||
923 | irda_connect_response(new); | 946 | irda_connect_response(new); |
924 | 947 | err = 0; | |
925 | return 0; | 948 | out: |
949 | unlock_kernel(); | ||
950 | return err; | ||
926 | } | 951 | } |
927 | 952 | ||
928 | /* | 953 | /* |
@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
955 | 980 | ||
956 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); | 981 | IRDA_DEBUG(2, "%s(%p)\n", __func__, self); |
957 | 982 | ||
983 | lock_kernel(); | ||
958 | /* Don't allow connect for Ultra sockets */ | 984 | /* Don't allow connect for Ultra sockets */ |
985 | err = -ESOCKTNOSUPPORT; | ||
959 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) | 986 | if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA)) |
960 | return -ESOCKTNOSUPPORT; | 987 | goto out; |
961 | 988 | ||
962 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 989 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
963 | sock->state = SS_CONNECTED; | 990 | sock->state = SS_CONNECTED; |
964 | return 0; /* Connect completed during a ERESTARTSYS event */ | 991 | err = 0; |
992 | goto out; /* Connect completed during a ERESTARTSYS event */ | ||
965 | } | 993 | } |
966 | 994 | ||
967 | if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { | 995 | if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) { |
968 | sock->state = SS_UNCONNECTED; | 996 | sock->state = SS_UNCONNECTED; |
969 | return -ECONNREFUSED; | 997 | err = -ECONNREFUSED; |
998 | goto out; | ||
970 | } | 999 | } |
971 | 1000 | ||
1001 | err = -EISCONN; /* No reconnect on a seqpacket socket */ | ||
972 | if (sk->sk_state == TCP_ESTABLISHED) | 1002 | if (sk->sk_state == TCP_ESTABLISHED) |
973 | return -EISCONN; /* No reconnect on a seqpacket socket */ | 1003 | goto out; |
974 | 1004 | ||
975 | sk->sk_state = TCP_CLOSE; | 1005 | sk->sk_state = TCP_CLOSE; |
976 | sock->state = SS_UNCONNECTED; | 1006 | sock->state = SS_UNCONNECTED; |
977 | 1007 | ||
1008 | err = -EINVAL; | ||
978 | if (addr_len != sizeof(struct sockaddr_irda)) | 1009 | if (addr_len != sizeof(struct sockaddr_irda)) |
979 | return -EINVAL; | 1010 | goto out; |
980 | 1011 | ||
981 | /* Check if user supplied any destination device address */ | 1012 | /* Check if user supplied any destination device address */ |
982 | if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) { | 1013 | if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) { |
@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
984 | err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); | 1015 | err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); |
985 | if (err) { | 1016 | if (err) { |
986 | IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__); | 1017 | IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__); |
987 | return err; | 1018 | goto out; |
988 | } | 1019 | } |
989 | } else { | 1020 | } else { |
990 | /* Use the one provided by the user */ | 1021 | /* Use the one provided by the user */ |
@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1000 | err = irda_find_lsap_sel(self, addr->sir_name); | 1031 | err = irda_find_lsap_sel(self, addr->sir_name); |
1001 | if (err) { | 1032 | if (err) { |
1002 | IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); | 1033 | IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); |
1003 | return err; | 1034 | goto out; |
1004 | } | 1035 | } |
1005 | } else { | 1036 | } else { |
1006 | /* Directly connect to the remote LSAP | 1037 | /* Directly connect to the remote LSAP |
@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, | |||
1025 | self->max_sdu_size_rx, NULL); | 1056 | self->max_sdu_size_rx, NULL); |
1026 | if (err) { | 1057 | if (err) { |
1027 | IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); | 1058 | IRDA_DEBUG(0, "%s(), connect failed!\n", __func__); |
1028 | return err; | 1059 | goto out; |
1029 | } | 1060 | } |
1030 | 1061 | ||
1031 | /* Now the loop */ | 1062 | /* Now the loop */ |
1063 | err = -EINPROGRESS; | ||
1032 | if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) | 1064 | if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) |
1033 | return -EINPROGRESS; | 1065 | goto out; |
1034 | 1066 | ||
1067 | err = -ERESTARTSYS; | ||
1035 | if (wait_event_interruptible(*(sk->sk_sleep), | 1068 | if (wait_event_interruptible(*(sk->sk_sleep), |
1036 | (sk->sk_state != TCP_SYN_SENT))) | 1069 | (sk->sk_state != TCP_SYN_SENT))) |
1037 | return -ERESTARTSYS; | 1070 | goto out; |
1038 | 1071 | ||
1039 | if (sk->sk_state != TCP_ESTABLISHED) { | 1072 | if (sk->sk_state != TCP_ESTABLISHED) { |
1040 | sock->state = SS_UNCONNECTED; | 1073 | sock->state = SS_UNCONNECTED; |
1041 | err = sock_error(sk); | 1074 | err = sock_error(sk); |
1042 | return err? err : -ECONNRESET; | 1075 | if (!err) |
1076 | err = -ECONNRESET; | ||
1077 | goto out; | ||
1043 | } | 1078 | } |
1044 | 1079 | ||
1045 | sock->state = SS_CONNECTED; | 1080 | sock->state = SS_CONNECTED; |
1046 | 1081 | ||
1047 | /* At this point, IrLMP has assigned our source address */ | 1082 | /* At this point, IrLMP has assigned our source address */ |
1048 | self->saddr = irttp_get_saddr(self->tsap); | 1083 | self->saddr = irttp_get_saddr(self->tsap); |
1049 | 1084 | err = 0; | |
1050 | return 0; | 1085 | out: |
1086 | unlock_kernel(); | ||
1087 | return err; | ||
1051 | } | 1088 | } |
1052 | 1089 | ||
1053 | static struct proto irda_proto = { | 1090 | static struct proto irda_proto = { |
@@ -1062,7 +1099,8 @@ static struct proto irda_proto = { | |||
1062 | * Create IrDA socket | 1099 | * Create IrDA socket |
1063 | * | 1100 | * |
1064 | */ | 1101 | */ |
1065 | static int irda_create(struct net *net, struct socket *sock, int protocol) | 1102 | static int irda_create(struct net *net, struct socket *sock, int protocol, |
1103 | int kern) | ||
1066 | { | 1104 | { |
1067 | struct sock *sk; | 1105 | struct sock *sk; |
1068 | struct irda_sock *self; | 1106 | struct irda_sock *self; |
@@ -1192,6 +1230,7 @@ static int irda_release(struct socket *sock) | |||
1192 | if (sk == NULL) | 1230 | if (sk == NULL) |
1193 | return 0; | 1231 | return 0; |
1194 | 1232 | ||
1233 | lock_kernel(); | ||
1195 | lock_sock(sk); | 1234 | lock_sock(sk); |
1196 | sk->sk_state = TCP_CLOSE; | 1235 | sk->sk_state = TCP_CLOSE; |
1197 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1236 | sk->sk_shutdown |= SEND_SHUTDOWN; |
@@ -1210,6 +1249,7 @@ static int irda_release(struct socket *sock) | |||
1210 | /* Destroy networking socket if we are the last reference on it, | 1249 | /* Destroy networking socket if we are the last reference on it, |
1211 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ | 1250 | * i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */ |
1212 | sock_put(sk); | 1251 | sock_put(sk); |
1252 | unlock_kernel(); | ||
1213 | 1253 | ||
1214 | /* Notes on socket locking and deallocation... - Jean II | 1254 | /* Notes on socket locking and deallocation... - Jean II |
1215 | * In theory we should put pairs of sock_hold() / sock_put() to | 1255 | * In theory we should put pairs of sock_hold() / sock_put() to |
@@ -1257,28 +1297,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1257 | 1297 | ||
1258 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1298 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1259 | 1299 | ||
1300 | lock_kernel(); | ||
1260 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ | 1301 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ |
1261 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | | 1302 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | |
1262 | MSG_NOSIGNAL)) | 1303 | MSG_NOSIGNAL)) { |
1263 | return -EINVAL; | 1304 | err = -EINVAL; |
1305 | goto out; | ||
1306 | } | ||
1264 | 1307 | ||
1265 | if (sk->sk_shutdown & SEND_SHUTDOWN) | 1308 | if (sk->sk_shutdown & SEND_SHUTDOWN) |
1266 | goto out_err; | 1309 | goto out_err; |
1267 | 1310 | ||
1268 | if (sk->sk_state != TCP_ESTABLISHED) | 1311 | if (sk->sk_state != TCP_ESTABLISHED) { |
1269 | return -ENOTCONN; | 1312 | err = -ENOTCONN; |
1313 | goto out; | ||
1314 | } | ||
1270 | 1315 | ||
1271 | self = irda_sk(sk); | 1316 | self = irda_sk(sk); |
1272 | 1317 | ||
1273 | /* Check if IrTTP is wants us to slow down */ | 1318 | /* Check if IrTTP is wants us to slow down */ |
1274 | 1319 | ||
1275 | if (wait_event_interruptible(*(sk->sk_sleep), | 1320 | if (wait_event_interruptible(*(sk->sk_sleep), |
1276 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) | 1321 | (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) { |
1277 | return -ERESTARTSYS; | 1322 | err = -ERESTARTSYS; |
1323 | goto out; | ||
1324 | } | ||
1278 | 1325 | ||
1279 | /* Check if we are still connected */ | 1326 | /* Check if we are still connected */ |
1280 | if (sk->sk_state != TCP_ESTABLISHED) | 1327 | if (sk->sk_state != TCP_ESTABLISHED) { |
1281 | return -ENOTCONN; | 1328 | err = -ENOTCONN; |
1329 | goto out; | ||
1330 | } | ||
1282 | 1331 | ||
1283 | /* Check that we don't send out too big frames */ | 1332 | /* Check that we don't send out too big frames */ |
1284 | if (len > self->max_data_size) { | 1333 | if (len > self->max_data_size) { |
@@ -1310,11 +1359,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1310 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1359 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
1311 | goto out_err; | 1360 | goto out_err; |
1312 | } | 1361 | } |
1362 | |||
1363 | unlock_kernel(); | ||
1313 | /* Tell client how much data we actually sent */ | 1364 | /* Tell client how much data we actually sent */ |
1314 | return len; | 1365 | return len; |
1315 | 1366 | ||
1316 | out_err: | 1367 | out_err: |
1317 | return sk_stream_error(sk, msg->msg_flags, err); | 1368 | err = sk_stream_error(sk, msg->msg_flags, err); |
1369 | out: | ||
1370 | unlock_kernel(); | ||
1371 | return err; | ||
1318 | 1372 | ||
1319 | } | 1373 | } |
1320 | 1374 | ||
@@ -1335,13 +1389,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1335 | 1389 | ||
1336 | IRDA_DEBUG(4, "%s()\n", __func__); | 1390 | IRDA_DEBUG(4, "%s()\n", __func__); |
1337 | 1391 | ||
1392 | lock_kernel(); | ||
1338 | if ((err = sock_error(sk)) < 0) | 1393 | if ((err = sock_error(sk)) < 0) |
1339 | return err; | 1394 | goto out; |
1340 | 1395 | ||
1341 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1396 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
1342 | flags & MSG_DONTWAIT, &err); | 1397 | flags & MSG_DONTWAIT, &err); |
1343 | if (!skb) | 1398 | if (!skb) |
1344 | return err; | 1399 | goto out; |
1345 | 1400 | ||
1346 | skb_reset_transport_header(skb); | 1401 | skb_reset_transport_header(skb); |
1347 | copied = skb->len; | 1402 | copied = skb->len; |
@@ -1369,8 +1424,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1369 | irttp_flow_request(self->tsap, FLOW_START); | 1424 | irttp_flow_request(self->tsap, FLOW_START); |
1370 | } | 1425 | } |
1371 | } | 1426 | } |
1372 | 1427 | unlock_kernel(); | |
1373 | return copied; | 1428 | return copied; |
1429 | |||
1430 | out: | ||
1431 | unlock_kernel(); | ||
1432 | return err; | ||
1374 | } | 1433 | } |
1375 | 1434 | ||
1376 | /* | 1435 | /* |
@@ -1388,15 +1447,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1388 | 1447 | ||
1389 | IRDA_DEBUG(3, "%s()\n", __func__); | 1448 | IRDA_DEBUG(3, "%s()\n", __func__); |
1390 | 1449 | ||
1450 | lock_kernel(); | ||
1391 | if ((err = sock_error(sk)) < 0) | 1451 | if ((err = sock_error(sk)) < 0) |
1392 | return err; | 1452 | goto out; |
1393 | 1453 | ||
1454 | err = -EINVAL; | ||
1394 | if (sock->flags & __SO_ACCEPTCON) | 1455 | if (sock->flags & __SO_ACCEPTCON) |
1395 | return(-EINVAL); | 1456 | goto out; |
1396 | 1457 | ||
1458 | err =-EOPNOTSUPP; | ||
1397 | if (flags & MSG_OOB) | 1459 | if (flags & MSG_OOB) |
1398 | return -EOPNOTSUPP; | 1460 | goto out; |
1399 | 1461 | ||
1462 | err = 0; | ||
1400 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); | 1463 | target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); |
1401 | timeo = sock_rcvtimeo(sk, noblock); | 1464 | timeo = sock_rcvtimeo(sk, noblock); |
1402 | 1465 | ||
@@ -1408,7 +1471,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1408 | 1471 | ||
1409 | if (skb == NULL) { | 1472 | if (skb == NULL) { |
1410 | DEFINE_WAIT(wait); | 1473 | DEFINE_WAIT(wait); |
1411 | int ret = 0; | 1474 | err = 0; |
1412 | 1475 | ||
1413 | if (copied >= target) | 1476 | if (copied >= target) |
1414 | break; | 1477 | break; |
@@ -1418,25 +1481,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1418 | /* | 1481 | /* |
1419 | * POSIX 1003.1g mandates this order. | 1482 | * POSIX 1003.1g mandates this order. |
1420 | */ | 1483 | */ |
1421 | ret = sock_error(sk); | 1484 | err = sock_error(sk); |
1422 | if (ret) | 1485 | if (err) |
1423 | ; | 1486 | ; |
1424 | else if (sk->sk_shutdown & RCV_SHUTDOWN) | 1487 | else if (sk->sk_shutdown & RCV_SHUTDOWN) |
1425 | ; | 1488 | ; |
1426 | else if (noblock) | 1489 | else if (noblock) |
1427 | ret = -EAGAIN; | 1490 | err = -EAGAIN; |
1428 | else if (signal_pending(current)) | 1491 | else if (signal_pending(current)) |
1429 | ret = sock_intr_errno(timeo); | 1492 | err = sock_intr_errno(timeo); |
1430 | else if (sk->sk_state != TCP_ESTABLISHED) | 1493 | else if (sk->sk_state != TCP_ESTABLISHED) |
1431 | ret = -ENOTCONN; | 1494 | err = -ENOTCONN; |
1432 | else if (skb_peek(&sk->sk_receive_queue) == NULL) | 1495 | else if (skb_peek(&sk->sk_receive_queue) == NULL) |
1433 | /* Wait process until data arrives */ | 1496 | /* Wait process until data arrives */ |
1434 | schedule(); | 1497 | schedule(); |
1435 | 1498 | ||
1436 | finish_wait(sk->sk_sleep, &wait); | 1499 | finish_wait(sk->sk_sleep, &wait); |
1437 | 1500 | ||
1438 | if (ret) | 1501 | if (err) |
1439 | return ret; | 1502 | goto out; |
1440 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 1503 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
1441 | break; | 1504 | break; |
1442 | 1505 | ||
@@ -1489,7 +1552,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, | |||
1489 | } | 1552 | } |
1490 | } | 1553 | } |
1491 | 1554 | ||
1492 | return copied; | 1555 | out: |
1556 | unlock_kernel(); | ||
1557 | return err ? : copied; | ||
1493 | } | 1558 | } |
1494 | 1559 | ||
1495 | /* | 1560 | /* |
@@ -1507,18 +1572,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1507 | struct sk_buff *skb; | 1572 | struct sk_buff *skb; |
1508 | int err; | 1573 | int err; |
1509 | 1574 | ||
1575 | lock_kernel(); | ||
1576 | |||
1510 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1577 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1511 | 1578 | ||
1579 | err = -EINVAL; | ||
1512 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1580 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
1513 | return -EINVAL; | 1581 | goto out; |
1514 | 1582 | ||
1515 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1583 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
1516 | send_sig(SIGPIPE, current, 0); | 1584 | send_sig(SIGPIPE, current, 0); |
1517 | return -EPIPE; | 1585 | err = -EPIPE; |
1586 | goto out; | ||
1518 | } | 1587 | } |
1519 | 1588 | ||
1589 | err = -ENOTCONN; | ||
1520 | if (sk->sk_state != TCP_ESTABLISHED) | 1590 | if (sk->sk_state != TCP_ESTABLISHED) |
1521 | return -ENOTCONN; | 1591 | goto out; |
1522 | 1592 | ||
1523 | self = irda_sk(sk); | 1593 | self = irda_sk(sk); |
1524 | 1594 | ||
@@ -1535,8 +1605,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1535 | 1605 | ||
1536 | skb = sock_alloc_send_skb(sk, len + self->max_header_size, | 1606 | skb = sock_alloc_send_skb(sk, len + self->max_header_size, |
1537 | msg->msg_flags & MSG_DONTWAIT, &err); | 1607 | msg->msg_flags & MSG_DONTWAIT, &err); |
1608 | err = -ENOBUFS; | ||
1538 | if (!skb) | 1609 | if (!skb) |
1539 | return -ENOBUFS; | 1610 | goto out; |
1540 | 1611 | ||
1541 | skb_reserve(skb, self->max_header_size); | 1612 | skb_reserve(skb, self->max_header_size); |
1542 | skb_reset_transport_header(skb); | 1613 | skb_reset_transport_header(skb); |
@@ -1546,7 +1617,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1546 | err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); | 1617 | err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); |
1547 | if (err) { | 1618 | if (err) { |
1548 | kfree_skb(skb); | 1619 | kfree_skb(skb); |
1549 | return err; | 1620 | goto out; |
1550 | } | 1621 | } |
1551 | 1622 | ||
1552 | /* | 1623 | /* |
@@ -1556,9 +1627,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock, | |||
1556 | err = irttp_udata_request(self->tsap, skb); | 1627 | err = irttp_udata_request(self->tsap, skb); |
1557 | if (err) { | 1628 | if (err) { |
1558 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1629 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
1559 | return err; | 1630 | goto out; |
1560 | } | 1631 | } |
1632 | unlock_kernel(); | ||
1561 | return len; | 1633 | return len; |
1634 | out: | ||
1635 | unlock_kernel(); | ||
1636 | return err; | ||
1562 | } | 1637 | } |
1563 | 1638 | ||
1564 | /* | 1639 | /* |
@@ -1580,12 +1655,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1580 | 1655 | ||
1581 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); | 1656 | IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len); |
1582 | 1657 | ||
1658 | lock_kernel(); | ||
1659 | err = -EINVAL; | ||
1583 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | 1660 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) |
1584 | return -EINVAL; | 1661 | goto out; |
1585 | 1662 | ||
1663 | err = -EPIPE; | ||
1586 | if (sk->sk_shutdown & SEND_SHUTDOWN) { | 1664 | if (sk->sk_shutdown & SEND_SHUTDOWN) { |
1587 | send_sig(SIGPIPE, current, 0); | 1665 | send_sig(SIGPIPE, current, 0); |
1588 | return -EPIPE; | 1666 | goto out; |
1589 | } | 1667 | } |
1590 | 1668 | ||
1591 | self = irda_sk(sk); | 1669 | self = irda_sk(sk); |
@@ -1593,16 +1671,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1593 | /* Check if an address was specified with sendto. Jean II */ | 1671 | /* Check if an address was specified with sendto. Jean II */ |
1594 | if (msg->msg_name) { | 1672 | if (msg->msg_name) { |
1595 | struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; | 1673 | struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name; |
1674 | err = -EINVAL; | ||
1596 | /* Check address, extract pid. Jean II */ | 1675 | /* Check address, extract pid. Jean II */ |
1597 | if (msg->msg_namelen < sizeof(*addr)) | 1676 | if (msg->msg_namelen < sizeof(*addr)) |
1598 | return -EINVAL; | 1677 | goto out; |
1599 | if (addr->sir_family != AF_IRDA) | 1678 | if (addr->sir_family != AF_IRDA) |
1600 | return -EINVAL; | 1679 | goto out; |
1601 | 1680 | ||
1602 | pid = addr->sir_lsap_sel; | 1681 | pid = addr->sir_lsap_sel; |
1603 | if (pid & 0x80) { | 1682 | if (pid & 0x80) { |
1604 | IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); | 1683 | IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__); |
1605 | return -EOPNOTSUPP; | 1684 | err = -EOPNOTSUPP; |
1685 | goto out; | ||
1606 | } | 1686 | } |
1607 | } else { | 1687 | } else { |
1608 | /* Check that the socket is properly bound to an Ultra | 1688 | /* Check that the socket is properly bound to an Ultra |
@@ -1611,7 +1691,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1611 | (sk->sk_state != TCP_ESTABLISHED)) { | 1691 | (sk->sk_state != TCP_ESTABLISHED)) { |
1612 | IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n", | 1692 | IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n", |
1613 | __func__); | 1693 | __func__); |
1614 | return -ENOTCONN; | 1694 | err = -ENOTCONN; |
1695 | goto out; | ||
1615 | } | 1696 | } |
1616 | /* Use PID from socket */ | 1697 | /* Use PID from socket */ |
1617 | bound = 1; | 1698 | bound = 1; |
@@ -1630,8 +1711,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1630 | 1711 | ||
1631 | skb = sock_alloc_send_skb(sk, len + self->max_header_size, | 1712 | skb = sock_alloc_send_skb(sk, len + self->max_header_size, |
1632 | msg->msg_flags & MSG_DONTWAIT, &err); | 1713 | msg->msg_flags & MSG_DONTWAIT, &err); |
1714 | err = -ENOBUFS; | ||
1633 | if (!skb) | 1715 | if (!skb) |
1634 | return -ENOBUFS; | 1716 | goto out; |
1635 | 1717 | ||
1636 | skb_reserve(skb, self->max_header_size); | 1718 | skb_reserve(skb, self->max_header_size); |
1637 | skb_reset_transport_header(skb); | 1719 | skb_reset_transport_header(skb); |
@@ -1641,16 +1723,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock, | |||
1641 | err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); | 1723 | err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); |
1642 | if (err) { | 1724 | if (err) { |
1643 | kfree_skb(skb); | 1725 | kfree_skb(skb); |
1644 | return err; | 1726 | goto out; |
1645 | } | 1727 | } |
1646 | 1728 | ||
1647 | err = irlmp_connless_data_request((bound ? self->lsap : NULL), | 1729 | err = irlmp_connless_data_request((bound ? self->lsap : NULL), |
1648 | skb, pid); | 1730 | skb, pid); |
1649 | if (err) { | 1731 | if (err) |
1650 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); | 1732 | IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err); |
1651 | return err; | 1733 | out: |
1652 | } | 1734 | unlock_kernel(); |
1653 | return len; | 1735 | return err ? : len; |
1654 | } | 1736 | } |
1655 | #endif /* CONFIG_IRDA_ULTRA */ | 1737 | #endif /* CONFIG_IRDA_ULTRA */ |
1656 | 1738 | ||
@@ -1664,6 +1746,8 @@ static int irda_shutdown(struct socket *sock, int how) | |||
1664 | 1746 | ||
1665 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); | 1747 | IRDA_DEBUG(1, "%s(%p)\n", __func__, self); |
1666 | 1748 | ||
1749 | lock_kernel(); | ||
1750 | |||
1667 | sk->sk_state = TCP_CLOSE; | 1751 | sk->sk_state = TCP_CLOSE; |
1668 | sk->sk_shutdown |= SEND_SHUTDOWN; | 1752 | sk->sk_shutdown |= SEND_SHUTDOWN; |
1669 | sk->sk_state_change(sk); | 1753 | sk->sk_state_change(sk); |
@@ -1684,6 +1768,8 @@ static int irda_shutdown(struct socket *sock, int how) | |||
1684 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ | 1768 | self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ |
1685 | self->saddr = 0x0; /* so IrLMP assign us any link */ | 1769 | self->saddr = 0x0; /* so IrLMP assign us any link */ |
1686 | 1770 | ||
1771 | unlock_kernel(); | ||
1772 | |||
1687 | return 0; | 1773 | return 0; |
1688 | } | 1774 | } |
1689 | 1775 | ||
@@ -1699,6 +1785,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
1699 | 1785 | ||
1700 | IRDA_DEBUG(4, "%s()\n", __func__); | 1786 | IRDA_DEBUG(4, "%s()\n", __func__); |
1701 | 1787 | ||
1788 | lock_kernel(); | ||
1702 | poll_wait(file, sk->sk_sleep, wait); | 1789 | poll_wait(file, sk->sk_sleep, wait); |
1703 | mask = 0; | 1790 | mask = 0; |
1704 | 1791 | ||
@@ -1746,18 +1833,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock, | |||
1746 | default: | 1833 | default: |
1747 | break; | 1834 | break; |
1748 | } | 1835 | } |
1836 | unlock_kernel(); | ||
1749 | return mask; | 1837 | return mask; |
1750 | } | 1838 | } |
1751 | 1839 | ||
1840 | static unsigned int irda_datagram_poll(struct file *file, struct socket *sock, | ||
1841 | poll_table *wait) | ||
1842 | { | ||
1843 | int err; | ||
1844 | |||
1845 | lock_kernel(); | ||
1846 | err = datagram_poll(file, sock, wait); | ||
1847 | unlock_kernel(); | ||
1848 | |||
1849 | return err; | ||
1850 | } | ||
1851 | |||
1752 | /* | 1852 | /* |
1753 | * Function irda_ioctl (sock, cmd, arg) | 1853 | * Function irda_ioctl (sock, cmd, arg) |
1754 | */ | 1854 | */ |
1755 | static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 1855 | static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
1756 | { | 1856 | { |
1757 | struct sock *sk = sock->sk; | 1857 | struct sock *sk = sock->sk; |
1858 | int err; | ||
1758 | 1859 | ||
1759 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); | 1860 | IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd); |
1760 | 1861 | ||
1862 | lock_kernel(); | ||
1863 | err = -EINVAL; | ||
1761 | switch (cmd) { | 1864 | switch (cmd) { |
1762 | case TIOCOUTQ: { | 1865 | case TIOCOUTQ: { |
1763 | long amount; | 1866 | long amount; |
@@ -1765,9 +1868,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1765 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1868 | amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
1766 | if (amount < 0) | 1869 | if (amount < 0) |
1767 | amount = 0; | 1870 | amount = 0; |
1768 | if (put_user(amount, (unsigned int __user *)arg)) | 1871 | err = put_user(amount, (unsigned int __user *)arg); |
1769 | return -EFAULT; | 1872 | break; |
1770 | return 0; | ||
1771 | } | 1873 | } |
1772 | 1874 | ||
1773 | case TIOCINQ: { | 1875 | case TIOCINQ: { |
@@ -1776,15 +1878,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1776 | /* These two are safe on a single CPU system as only user tasks fiddle here */ | 1878 | /* These two are safe on a single CPU system as only user tasks fiddle here */ |
1777 | if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) | 1879 | if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) |
1778 | amount = skb->len; | 1880 | amount = skb->len; |
1779 | if (put_user(amount, (unsigned int __user *)arg)) | 1881 | err = put_user(amount, (unsigned int __user *)arg); |
1780 | return -EFAULT; | 1882 | break; |
1781 | return 0; | ||
1782 | } | 1883 | } |
1783 | 1884 | ||
1784 | case SIOCGSTAMP: | 1885 | case SIOCGSTAMP: |
1785 | if (sk != NULL) | 1886 | if (sk != NULL) |
1786 | return sock_get_timestamp(sk, (struct timeval __user *)arg); | 1887 | err = sock_get_timestamp(sk, (struct timeval __user *)arg); |
1787 | return -EINVAL; | 1888 | break; |
1788 | 1889 | ||
1789 | case SIOCGIFADDR: | 1890 | case SIOCGIFADDR: |
1790 | case SIOCSIFADDR: | 1891 | case SIOCSIFADDR: |
@@ -1796,14 +1897,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1796 | case SIOCSIFNETMASK: | 1897 | case SIOCSIFNETMASK: |
1797 | case SIOCGIFMETRIC: | 1898 | case SIOCGIFMETRIC: |
1798 | case SIOCSIFMETRIC: | 1899 | case SIOCSIFMETRIC: |
1799 | return -EINVAL; | 1900 | break; |
1800 | default: | 1901 | default: |
1801 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); | 1902 | IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__); |
1802 | return -ENOIOCTLCMD; | 1903 | err = -ENOIOCTLCMD; |
1803 | } | 1904 | } |
1905 | unlock_kernel(); | ||
1804 | 1906 | ||
1805 | /*NOTREACHED*/ | 1907 | return err; |
1806 | return 0; | ||
1807 | } | 1908 | } |
1808 | 1909 | ||
1809 | #ifdef CONFIG_COMPAT | 1910 | #ifdef CONFIG_COMPAT |
@@ -1825,7 +1926,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon | |||
1825 | * Set some options for the socket | 1926 | * Set some options for the socket |
1826 | * | 1927 | * |
1827 | */ | 1928 | */ |
1828 | static int irda_setsockopt(struct socket *sock, int level, int optname, | 1929 | static int __irda_setsockopt(struct socket *sock, int level, int optname, |
1829 | char __user *optval, unsigned int optlen) | 1930 | char __user *optval, unsigned int optlen) |
1830 | { | 1931 | { |
1831 | struct sock *sk = sock->sk; | 1932 | struct sock *sk = sock->sk; |
@@ -2083,6 +2184,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname, | |||
2083 | return 0; | 2184 | return 0; |
2084 | } | 2185 | } |
2085 | 2186 | ||
2187 | static int irda_setsockopt(struct socket *sock, int level, int optname, | ||
2188 | char __user *optval, unsigned int optlen) | ||
2189 | { | ||
2190 | int err; | ||
2191 | |||
2192 | lock_kernel(); | ||
2193 | err = __irda_setsockopt(sock, level, optname, optval, optlen); | ||
2194 | unlock_kernel(); | ||
2195 | |||
2196 | return err; | ||
2197 | } | ||
2198 | |||
2086 | /* | 2199 | /* |
2087 | * Function irda_extract_ias_value(ias_opt, ias_value) | 2200 | * Function irda_extract_ias_value(ias_opt, ias_value) |
2088 | * | 2201 | * |
@@ -2135,7 +2248,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt, | |||
2135 | /* | 2248 | /* |
2136 | * Function irda_getsockopt (sock, level, optname, optval, optlen) | 2249 | * Function irda_getsockopt (sock, level, optname, optval, optlen) |
2137 | */ | 2250 | */ |
2138 | static int irda_getsockopt(struct socket *sock, int level, int optname, | 2251 | static int __irda_getsockopt(struct socket *sock, int level, int optname, |
2139 | char __user *optval, int __user *optlen) | 2252 | char __user *optval, int __user *optlen) |
2140 | { | 2253 | { |
2141 | struct sock *sk = sock->sk; | 2254 | struct sock *sk = sock->sk; |
@@ -2463,13 +2576,25 @@ bed: | |||
2463 | return 0; | 2576 | return 0; |
2464 | } | 2577 | } |
2465 | 2578 | ||
2579 | static int irda_getsockopt(struct socket *sock, int level, int optname, | ||
2580 | char __user *optval, int __user *optlen) | ||
2581 | { | ||
2582 | int err; | ||
2583 | |||
2584 | lock_kernel(); | ||
2585 | err = __irda_getsockopt(sock, level, optname, optval, optlen); | ||
2586 | unlock_kernel(); | ||
2587 | |||
2588 | return err; | ||
2589 | } | ||
2590 | |||
2466 | static const struct net_proto_family irda_family_ops = { | 2591 | static const struct net_proto_family irda_family_ops = { |
2467 | .family = PF_IRDA, | 2592 | .family = PF_IRDA, |
2468 | .create = irda_create, | 2593 | .create = irda_create, |
2469 | .owner = THIS_MODULE, | 2594 | .owner = THIS_MODULE, |
2470 | }; | 2595 | }; |
2471 | 2596 | ||
2472 | static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { | 2597 | static const struct proto_ops irda_stream_ops = { |
2473 | .family = PF_IRDA, | 2598 | .family = PF_IRDA, |
2474 | .owner = THIS_MODULE, | 2599 | .owner = THIS_MODULE, |
2475 | .release = irda_release, | 2600 | .release = irda_release, |
@@ -2493,7 +2618,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { | |||
2493 | .sendpage = sock_no_sendpage, | 2618 | .sendpage = sock_no_sendpage, |
2494 | }; | 2619 | }; |
2495 | 2620 | ||
2496 | static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { | 2621 | static const struct proto_ops irda_seqpacket_ops = { |
2497 | .family = PF_IRDA, | 2622 | .family = PF_IRDA, |
2498 | .owner = THIS_MODULE, | 2623 | .owner = THIS_MODULE, |
2499 | .release = irda_release, | 2624 | .release = irda_release, |
@@ -2502,7 +2627,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { | |||
2502 | .socketpair = sock_no_socketpair, | 2627 | .socketpair = sock_no_socketpair, |
2503 | .accept = irda_accept, | 2628 | .accept = irda_accept, |
2504 | .getname = irda_getname, | 2629 | .getname = irda_getname, |
2505 | .poll = datagram_poll, | 2630 | .poll = irda_datagram_poll, |
2506 | .ioctl = irda_ioctl, | 2631 | .ioctl = irda_ioctl, |
2507 | #ifdef CONFIG_COMPAT | 2632 | #ifdef CONFIG_COMPAT |
2508 | .compat_ioctl = irda_compat_ioctl, | 2633 | .compat_ioctl = irda_compat_ioctl, |
@@ -2517,7 +2642,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { | |||
2517 | .sendpage = sock_no_sendpage, | 2642 | .sendpage = sock_no_sendpage, |
2518 | }; | 2643 | }; |
2519 | 2644 | ||
2520 | static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { | 2645 | static const struct proto_ops irda_dgram_ops = { |
2521 | .family = PF_IRDA, | 2646 | .family = PF_IRDA, |
2522 | .owner = THIS_MODULE, | 2647 | .owner = THIS_MODULE, |
2523 | .release = irda_release, | 2648 | .release = irda_release, |
@@ -2526,7 +2651,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { | |||
2526 | .socketpair = sock_no_socketpair, | 2651 | .socketpair = sock_no_socketpair, |
2527 | .accept = irda_accept, | 2652 | .accept = irda_accept, |
2528 | .getname = irda_getname, | 2653 | .getname = irda_getname, |
2529 | .poll = datagram_poll, | 2654 | .poll = irda_datagram_poll, |
2530 | .ioctl = irda_ioctl, | 2655 | .ioctl = irda_ioctl, |
2531 | #ifdef CONFIG_COMPAT | 2656 | #ifdef CONFIG_COMPAT |
2532 | .compat_ioctl = irda_compat_ioctl, | 2657 | .compat_ioctl = irda_compat_ioctl, |
@@ -2542,7 +2667,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { | |||
2542 | }; | 2667 | }; |
2543 | 2668 | ||
2544 | #ifdef CONFIG_IRDA_ULTRA | 2669 | #ifdef CONFIG_IRDA_ULTRA |
2545 | static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { | 2670 | static const struct proto_ops irda_ultra_ops = { |
2546 | .family = PF_IRDA, | 2671 | .family = PF_IRDA, |
2547 | .owner = THIS_MODULE, | 2672 | .owner = THIS_MODULE, |
2548 | .release = irda_release, | 2673 | .release = irda_release, |
@@ -2551,7 +2676,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { | |||
2551 | .socketpair = sock_no_socketpair, | 2676 | .socketpair = sock_no_socketpair, |
2552 | .accept = sock_no_accept, | 2677 | .accept = sock_no_accept, |
2553 | .getname = irda_getname, | 2678 | .getname = irda_getname, |
2554 | .poll = datagram_poll, | 2679 | .poll = irda_datagram_poll, |
2555 | .ioctl = irda_ioctl, | 2680 | .ioctl = irda_ioctl, |
2556 | #ifdef CONFIG_COMPAT | 2681 | #ifdef CONFIG_COMPAT |
2557 | .compat_ioctl = irda_compat_ioctl, | 2682 | .compat_ioctl = irda_compat_ioctl, |
@@ -2567,13 +2692,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { | |||
2567 | }; | 2692 | }; |
2568 | #endif /* CONFIG_IRDA_ULTRA */ | 2693 | #endif /* CONFIG_IRDA_ULTRA */ |
2569 | 2694 | ||
2570 | SOCKOPS_WRAP(irda_stream, PF_IRDA); | ||
2571 | SOCKOPS_WRAP(irda_seqpacket, PF_IRDA); | ||
2572 | SOCKOPS_WRAP(irda_dgram, PF_IRDA); | ||
2573 | #ifdef CONFIG_IRDA_ULTRA | ||
2574 | SOCKOPS_WRAP(irda_ultra, PF_IRDA); | ||
2575 | #endif /* CONFIG_IRDA_ULTRA */ | ||
2576 | |||
2577 | /* | 2695 | /* |
2578 | * Function irsock_init (pro) | 2696 | * Function irsock_init (pro) |
2579 | * | 2697 | * |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 3aebabb158a8..1e428863574f 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -481,7 +481,8 @@ static struct sock *iucv_sock_alloc(struct socket *sock, int proto, gfp_t prio) | |||
481 | } | 481 | } |
482 | 482 | ||
483 | /* Create an IUCV socket */ | 483 | /* Create an IUCV socket */ |
484 | static int iucv_sock_create(struct net *net, struct socket *sock, int protocol) | 484 | static int iucv_sock_create(struct net *net, struct socket *sock, int protocol, |
485 | int kern) | ||
485 | { | 486 | { |
486 | struct sock *sk; | 487 | struct sock *sk; |
487 | 488 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index 472f6594184a..86b2c22d0918 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -177,7 +177,8 @@ static struct proto key_proto = { | |||
177 | .obj_size = sizeof(struct pfkey_sock), | 177 | .obj_size = sizeof(struct pfkey_sock), |
178 | }; | 178 | }; |
179 | 179 | ||
180 | static int pfkey_create(struct net *net, struct socket *sock, int protocol) | 180 | static int pfkey_create(struct net *net, struct socket *sock, int protocol, |
181 | int kern) | ||
181 | { | 182 | { |
182 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); | 183 | struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id); |
183 | struct sock *sk; | 184 | struct sock *sk; |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 4866b4fb0c27..5266c286b260 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -140,14 +140,17 @@ static struct proto llc_proto = { | |||
140 | 140 | ||
141 | /** | 141 | /** |
142 | * llc_ui_create - alloc and init a new llc_ui socket | 142 | * llc_ui_create - alloc and init a new llc_ui socket |
143 | * @net: network namespace (must be default network) | ||
143 | * @sock: Socket to initialize and attach allocated sk to. | 144 | * @sock: Socket to initialize and attach allocated sk to. |
144 | * @protocol: Unused. | 145 | * @protocol: Unused. |
146 | * @kern: on behalf of kernel or userspace | ||
145 | * | 147 | * |
146 | * Allocate and initialize a new llc_ui socket, validate the user wants a | 148 | * Allocate and initialize a new llc_ui socket, validate the user wants a |
147 | * socket type we have available. | 149 | * socket type we have available. |
148 | * Returns 0 upon success, negative upon failure. | 150 | * Returns 0 upon success, negative upon failure. |
149 | */ | 151 | */ |
150 | static int llc_ui_create(struct net *net, struct socket *sock, int protocol) | 152 | static int llc_ui_create(struct net *net, struct socket *sock, int protocol, |
153 | int kern) | ||
151 | { | 154 | { |
152 | struct sock *sk; | 155 | struct sock *sk; |
153 | int rc = -ESOCKTNOSUPPORT; | 156 | int rc = -ESOCKTNOSUPPORT; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index bd765f30dba2..b09948ceec4a 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -666,26 +666,25 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
666 | 666 | ||
667 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 667 | state = &sta->ampdu_mlme.tid_state_tx[tid]; |
668 | 668 | ||
669 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
670 | |||
669 | spin_lock_bh(&sta->lock); | 671 | spin_lock_bh(&sta->lock); |
670 | 672 | ||
671 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 673 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) |
672 | spin_unlock_bh(&sta->lock); | 674 | goto timer_still_needed; |
673 | return; | ||
674 | } | ||
675 | 675 | ||
676 | if (mgmt->u.action.u.addba_resp.dialog_token != | 676 | if (mgmt->u.action.u.addba_resp.dialog_token != |
677 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | 677 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { |
678 | spin_unlock_bh(&sta->lock); | ||
679 | #ifdef CONFIG_MAC80211_HT_DEBUG | 678 | #ifdef CONFIG_MAC80211_HT_DEBUG |
680 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | 679 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); |
681 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 680 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
682 | return; | 681 | goto timer_still_needed; |
683 | } | 682 | } |
684 | 683 | ||
685 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
686 | #ifdef CONFIG_MAC80211_HT_DEBUG | 684 | #ifdef CONFIG_MAC80211_HT_DEBUG |
687 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | 685 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); |
688 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 686 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
687 | |||
689 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 688 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
690 | == WLAN_STATUS_SUCCESS) { | 689 | == WLAN_STATUS_SUCCESS) { |
691 | u8 curstate = *state; | 690 | u8 curstate = *state; |
@@ -699,5 +698,11 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
699 | } else { | 698 | } else { |
700 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); | 699 | ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); |
701 | } | 700 | } |
701 | |||
702 | goto out; | ||
703 | |||
704 | timer_still_needed: | ||
705 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
706 | out: | ||
702 | spin_unlock_bh(&sta->lock); | 707 | spin_unlock_bh(&sta->lock); |
703 | } | 708 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a0c7eb18a76d..56319b51d170 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -72,6 +72,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
72 | struct ieee80211_sub_if_data *sdata; | 72 | struct ieee80211_sub_if_data *sdata; |
73 | int ret; | 73 | int ret; |
74 | 74 | ||
75 | if (netif_running(dev)) | ||
76 | return -EBUSY; | ||
77 | |||
75 | if (!nl80211_type_check(type)) | 78 | if (!nl80211_type_check(type)) |
76 | return -EINVAL; | 79 | return -EINVAL; |
77 | 80 | ||
@@ -81,9 +84,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
81 | if (ret) | 84 | if (ret) |
82 | return ret; | 85 | return ret; |
83 | 86 | ||
84 | if (netif_running(sdata->dev)) | ||
85 | return -EBUSY; | ||
86 | |||
87 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 87 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
88 | ieee80211_sdata_set_mesh_id(sdata, | 88 | ieee80211_sdata_set_mesh_id(sdata, |
89 | params->mesh_id_len, | 89 | params->mesh_id_len, |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 0891bfb06996..48ef1a282b91 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -153,7 +153,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
153 | if (net_ratelimit()) | 153 | if (net_ratelimit()) |
154 | printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n", | 154 | printk(KERN_DEBUG "delba from %pM (%s) tid %d reason code %d\n", |
155 | mgmt->sa, initiator ? "initiator" : "recipient", tid, | 155 | mgmt->sa, initiator ? "initiator" : "recipient", tid, |
156 | mgmt->u.action.u.delba.reason_code); | 156 | le16_to_cpu(mgmt->u.action.u.delba.reason_code)); |
157 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 157 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
158 | 158 | ||
159 | if (initiator == WLAN_BACK_INITIATOR) | 159 | if (initiator == WLAN_BACK_INITIATOR) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 6ae288387a11..fbffce90edbc 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -73,6 +73,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
73 | struct ieee80211_mgmt *mgmt; | 73 | struct ieee80211_mgmt *mgmt; |
74 | u8 *pos; | 74 | u8 *pos; |
75 | struct ieee80211_supported_band *sband; | 75 | struct ieee80211_supported_band *sband; |
76 | struct cfg80211_bss *bss; | ||
76 | u32 bss_change; | 77 | u32 bss_change; |
77 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 78 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
78 | 79 | ||
@@ -177,8 +178,9 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
177 | mod_timer(&ifibss->timer, | 178 | mod_timer(&ifibss->timer, |
178 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 179 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
179 | 180 | ||
180 | cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, | 181 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, |
181 | mgmt, skb->len, 0, GFP_KERNEL); | 182 | mgmt, skb->len, 0, GFP_KERNEL); |
183 | cfg80211_put_bss(bss); | ||
182 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 184 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
183 | } | 185 | } |
184 | 186 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 7c9ec3dee96e..0cdfb388a191 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -1350,6 +1350,11 @@ err_stat: | |||
1350 | return ret; | 1350 | return ret; |
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | s16 (*nf_ct_nat_offset)(const struct nf_conn *ct, | ||
1354 | enum ip_conntrack_dir dir, | ||
1355 | u32 seq); | ||
1356 | EXPORT_SYMBOL_GPL(nf_ct_nat_offset); | ||
1357 | |||
1353 | int nf_conntrack_init(struct net *net) | 1358 | int nf_conntrack_init(struct net *net) |
1354 | { | 1359 | { |
1355 | int ret; | 1360 | int ret; |
@@ -1367,6 +1372,9 @@ int nf_conntrack_init(struct net *net) | |||
1367 | /* For use by REJECT target */ | 1372 | /* For use by REJECT target */ |
1368 | rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); | 1373 | rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach); |
1369 | rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); | 1374 | rcu_assign_pointer(nf_ct_destroy, destroy_conntrack); |
1375 | |||
1376 | /* Howto get NAT offsets */ | ||
1377 | rcu_assign_pointer(nf_ct_nat_offset, NULL); | ||
1370 | } | 1378 | } |
1371 | return 0; | 1379 | return 0; |
1372 | 1380 | ||
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 97a82ba75376..ba2b76937283 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -492,6 +492,21 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, | |||
492 | } | 492 | } |
493 | } | 493 | } |
494 | 494 | ||
495 | #ifdef CONFIG_NF_NAT_NEEDED | ||
496 | static inline s16 nat_offset(const struct nf_conn *ct, | ||
497 | enum ip_conntrack_dir dir, | ||
498 | u32 seq) | ||
499 | { | ||
500 | typeof(nf_ct_nat_offset) get_offset = rcu_dereference(nf_ct_nat_offset); | ||
501 | |||
502 | return get_offset != NULL ? get_offset(ct, dir, seq) : 0; | ||
503 | } | ||
504 | #define NAT_OFFSET(pf, ct, dir, seq) \ | ||
505 | (pf == NFPROTO_IPV4 ? nat_offset(ct, dir, seq) : 0) | ||
506 | #else | ||
507 | #define NAT_OFFSET(pf, ct, dir, seq) 0 | ||
508 | #endif | ||
509 | |||
495 | static bool tcp_in_window(const struct nf_conn *ct, | 510 | static bool tcp_in_window(const struct nf_conn *ct, |
496 | struct ip_ct_tcp *state, | 511 | struct ip_ct_tcp *state, |
497 | enum ip_conntrack_dir dir, | 512 | enum ip_conntrack_dir dir, |
@@ -506,6 +521,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
506 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; | 521 | struct ip_ct_tcp_state *receiver = &state->seen[!dir]; |
507 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; | 522 | const struct nf_conntrack_tuple *tuple = &ct->tuplehash[dir].tuple; |
508 | __u32 seq, ack, sack, end, win, swin; | 523 | __u32 seq, ack, sack, end, win, swin; |
524 | s16 receiver_offset; | ||
509 | bool res; | 525 | bool res; |
510 | 526 | ||
511 | /* | 527 | /* |
@@ -519,11 +535,16 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
519 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) | 535 | if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM) |
520 | tcp_sack(skb, dataoff, tcph, &sack); | 536 | tcp_sack(skb, dataoff, tcph, &sack); |
521 | 537 | ||
538 | /* Take into account NAT sequence number mangling */ | ||
539 | receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1); | ||
540 | ack -= receiver_offset; | ||
541 | sack -= receiver_offset; | ||
542 | |||
522 | pr_debug("tcp_in_window: START\n"); | 543 | pr_debug("tcp_in_window: START\n"); |
523 | pr_debug("tcp_in_window: "); | 544 | pr_debug("tcp_in_window: "); |
524 | nf_ct_dump_tuple(tuple); | 545 | nf_ct_dump_tuple(tuple); |
525 | pr_debug("seq=%u ack=%u sack=%u win=%u end=%u\n", | 546 | pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", |
526 | seq, ack, sack, win, end); | 547 | seq, ack, receiver_offset, sack, receiver_offset, win, end); |
527 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 548 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
528 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 549 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
529 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 550 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
@@ -613,8 +634,8 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
613 | 634 | ||
614 | pr_debug("tcp_in_window: "); | 635 | pr_debug("tcp_in_window: "); |
615 | nf_ct_dump_tuple(tuple); | 636 | nf_ct_dump_tuple(tuple); |
616 | pr_debug("seq=%u ack=%u sack =%u win=%u end=%u\n", | 637 | pr_debug("seq=%u ack=%u+(%d) sack=%u+(%d) win=%u end=%u\n", |
617 | seq, ack, sack, win, end); | 638 | seq, ack, receiver_offset, sack, receiver_offset, win, end); |
618 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " | 639 | pr_debug("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i " |
619 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | 640 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", |
620 | sender->td_end, sender->td_maxend, sender->td_maxwin, | 641 | sender->td_end, sender->td_maxend, sender->td_maxwin, |
@@ -700,7 +721,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
700 | before(seq, sender->td_maxend + 1) ? | 721 | before(seq, sender->td_maxend + 1) ? |
701 | after(end, sender->td_end - receiver->td_maxwin - 1) ? | 722 | after(end, sender->td_end - receiver->td_maxwin - 1) ? |
702 | before(sack, receiver->td_end + 1) ? | 723 | before(sack, receiver->td_end + 1) ? |
703 | after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG" | 724 | after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1) ? "BUG" |
704 | : "ACK is under the lower bound (possible overly delayed ACK)" | 725 | : "ACK is under the lower bound (possible overly delayed ACK)" |
705 | : "ACK is over the upper bound (ACKed data not seen yet)" | 726 | : "ACK is over the upper bound (ACKed data not seen yet)" |
706 | : "SEQ is under the lower bound (already ACKed data retransmitted)" | 727 | : "SEQ is under the lower bound (already ACKed data retransmitted)" |
@@ -715,39 +736,6 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
715 | return res; | 736 | return res; |
716 | } | 737 | } |
717 | 738 | ||
718 | #ifdef CONFIG_NF_NAT_NEEDED | ||
719 | /* Update sender->td_end after NAT successfully mangled the packet */ | ||
720 | /* Caller must linearize skb at tcp header. */ | ||
721 | void nf_conntrack_tcp_update(const struct sk_buff *skb, | ||
722 | unsigned int dataoff, | ||
723 | struct nf_conn *ct, int dir, | ||
724 | s16 offset) | ||
725 | { | ||
726 | const struct tcphdr *tcph = (const void *)skb->data + dataoff; | ||
727 | const struct ip_ct_tcp_state *sender = &ct->proto.tcp.seen[dir]; | ||
728 | const struct ip_ct_tcp_state *receiver = &ct->proto.tcp.seen[!dir]; | ||
729 | __u32 end; | ||
730 | |||
731 | end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, dataoff, tcph); | ||
732 | |||
733 | spin_lock_bh(&ct->lock); | ||
734 | /* | ||
735 | * We have to worry for the ack in the reply packet only... | ||
736 | */ | ||
737 | if (ct->proto.tcp.seen[dir].td_end + offset == end) | ||
738 | ct->proto.tcp.seen[dir].td_end = end; | ||
739 | ct->proto.tcp.last_end = end; | ||
740 | spin_unlock_bh(&ct->lock); | ||
741 | pr_debug("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " | ||
742 | "receiver end=%u maxend=%u maxwin=%u scale=%i\n", | ||
743 | sender->td_end, sender->td_maxend, sender->td_maxwin, | ||
744 | sender->td_scale, | ||
745 | receiver->td_end, receiver->td_maxend, receiver->td_maxwin, | ||
746 | receiver->td_scale); | ||
747 | } | ||
748 | EXPORT_SYMBOL_GPL(nf_conntrack_tcp_update); | ||
749 | #endif | ||
750 | |||
751 | #define TH_FIN 0x01 | 739 | #define TH_FIN 0x01 |
752 | #define TH_SYN 0x02 | 740 | #define TH_SYN 0x02 |
753 | #define TH_RST 0x04 | 741 | #define TH_RST 0x04 |
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index 680980954395..38f03f75a636 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
@@ -103,7 +103,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
103 | const struct nf_conntrack_tuple *tuple, | 103 | const struct nf_conntrack_tuple *tuple, |
104 | const union nf_inet_addr *addr, | 104 | const union nf_inet_addr *addr, |
105 | const union nf_inet_addr *mask, | 105 | const union nf_inet_addr *mask, |
106 | const struct xt_match *match) | 106 | u_int8_t family) |
107 | { | 107 | { |
108 | const struct nf_conntrack_tuple_hash *found; | 108 | const struct nf_conntrack_tuple_hash *found; |
109 | struct xt_connlimit_conn *conn; | 109 | struct xt_connlimit_conn *conn; |
@@ -113,8 +113,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
113 | bool addit = true; | 113 | bool addit = true; |
114 | int matches = 0; | 114 | int matches = 0; |
115 | 115 | ||
116 | 116 | if (family == NFPROTO_IPV6) | |
117 | if (match->family == NFPROTO_IPV6) | ||
118 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; | 117 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; |
119 | else | 118 | else |
120 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; | 119 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; |
@@ -157,8 +156,7 @@ static int count_them(struct xt_connlimit_data *data, | |||
157 | continue; | 156 | continue; |
158 | } | 157 | } |
159 | 158 | ||
160 | if (same_source_net(addr, mask, &conn->tuple.src.u3, | 159 | if (same_source_net(addr, mask, &conn->tuple.src.u3, family)) |
161 | match->family)) | ||
162 | /* same source network -> be counted! */ | 160 | /* same source network -> be counted! */ |
163 | ++matches; | 161 | ++matches; |
164 | nf_ct_put(found_ct); | 162 | nf_ct_put(found_ct); |
@@ -207,7 +205,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) | |||
207 | 205 | ||
208 | spin_lock_bh(&info->data->lock); | 206 | spin_lock_bh(&info->data->lock); |
209 | connections = count_them(info->data, tuple_ptr, &addr, | 207 | connections = count_them(info->data, tuple_ptr, &addr, |
210 | &info->mask, par->match); | 208 | &info->mask, par->family); |
211 | spin_unlock_bh(&info->data->lock); | 209 | spin_unlock_bh(&info->data->lock); |
212 | 210 | ||
213 | if (connections < 0) { | 211 | if (connections < 0) { |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index fb357f010189..3dfe2bac8623 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -472,13 +472,12 @@ int netlbl_unlhsh_add(struct net *net, | |||
472 | 472 | ||
473 | rcu_read_lock(); | 473 | rcu_read_lock(); |
474 | if (dev_name != NULL) { | 474 | if (dev_name != NULL) { |
475 | dev = dev_get_by_name(net, dev_name); | 475 | dev = dev_get_by_name_rcu(net, dev_name); |
476 | if (dev == NULL) { | 476 | if (dev == NULL) { |
477 | ret_val = -ENODEV; | 477 | ret_val = -ENODEV; |
478 | goto unlhsh_add_return; | 478 | goto unlhsh_add_return; |
479 | } | 479 | } |
480 | ifindex = dev->ifindex; | 480 | ifindex = dev->ifindex; |
481 | dev_put(dev); | ||
482 | iface = netlbl_unlhsh_search_iface(ifindex); | 481 | iface = netlbl_unlhsh_search_iface(ifindex); |
483 | } else { | 482 | } else { |
484 | ifindex = 0; | 483 | ifindex = 0; |
@@ -737,13 +736,12 @@ int netlbl_unlhsh_remove(struct net *net, | |||
737 | 736 | ||
738 | rcu_read_lock(); | 737 | rcu_read_lock(); |
739 | if (dev_name != NULL) { | 738 | if (dev_name != NULL) { |
740 | dev = dev_get_by_name(net, dev_name); | 739 | dev = dev_get_by_name_rcu(net, dev_name); |
741 | if (dev == NULL) { | 740 | if (dev == NULL) { |
742 | ret_val = -ENODEV; | 741 | ret_val = -ENODEV; |
743 | goto unlhsh_remove_return; | 742 | goto unlhsh_remove_return; |
744 | } | 743 | } |
745 | iface = netlbl_unlhsh_search_iface(dev->ifindex); | 744 | iface = netlbl_unlhsh_search_iface(dev->ifindex); |
746 | dev_put(dev); | ||
747 | } else | 745 | } else |
748 | iface = rcu_dereference(netlbl_unlhsh_def); | 746 | iface = rcu_dereference(netlbl_unlhsh_def); |
749 | if (iface == NULL) { | 747 | if (iface == NULL) { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 0cd2d8829313..aea805c98da3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -428,7 +428,8 @@ static int __netlink_create(struct net *net, struct socket *sock, | |||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | static int netlink_create(struct net *net, struct socket *sock, int protocol) | 431 | static int netlink_create(struct net *net, struct socket *sock, int protocol, |
432 | int kern) | ||
432 | { | 433 | { |
433 | struct module *module = NULL; | 434 | struct module *module = NULL; |
434 | struct mutex *cb_mutex; | 435 | struct mutex *cb_mutex; |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 281fa597cae5..4bdd5697f63b 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -425,7 +425,8 @@ static struct proto nr_proto = { | |||
425 | .obj_size = sizeof(struct nr_sock), | 425 | .obj_size = sizeof(struct nr_sock), |
426 | }; | 426 | }; |
427 | 427 | ||
428 | static int nr_create(struct net *net, struct socket *sock, int protocol) | 428 | static int nr_create(struct net *net, struct socket *sock, int protocol, |
429 | int kern) | ||
429 | { | 430 | { |
430 | struct sock *sk; | 431 | struct sock *sk; |
431 | struct nr_sock *nr; | 432 | struct nr_sock *nr; |
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 4eb1ac9a7679..aacba76070fc 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c | |||
@@ -597,15 +597,15 @@ struct net_device *nr_dev_first(void) | |||
597 | { | 597 | { |
598 | struct net_device *dev, *first = NULL; | 598 | struct net_device *dev, *first = NULL; |
599 | 599 | ||
600 | read_lock(&dev_base_lock); | 600 | rcu_read_lock(); |
601 | for_each_netdev(&init_net, dev) { | 601 | for_each_netdev_rcu(&init_net, dev) { |
602 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM) | 602 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM) |
603 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) | 603 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) |
604 | first = dev; | 604 | first = dev; |
605 | } | 605 | } |
606 | if (first) | 606 | if (first) |
607 | dev_hold(first); | 607 | dev_hold(first); |
608 | read_unlock(&dev_base_lock); | 608 | rcu_read_unlock(); |
609 | 609 | ||
610 | return first; | 610 | return first; |
611 | } | 611 | } |
@@ -617,16 +617,17 @@ struct net_device *nr_dev_get(ax25_address *addr) | |||
617 | { | 617 | { |
618 | struct net_device *dev; | 618 | struct net_device *dev; |
619 | 619 | ||
620 | read_lock(&dev_base_lock); | 620 | rcu_read_lock(); |
621 | for_each_netdev(&init_net, dev) { | 621 | for_each_netdev_rcu(&init_net, dev) { |
622 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { | 622 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && |
623 | ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) { | ||
623 | dev_hold(dev); | 624 | dev_hold(dev); |
624 | goto out; | 625 | goto out; |
625 | } | 626 | } |
626 | } | 627 | } |
627 | dev = NULL; | 628 | dev = NULL; |
628 | out: | 629 | out: |
629 | read_unlock(&dev_base_lock); | 630 | rcu_read_unlock(); |
630 | return dev; | 631 | return dev; |
631 | } | 632 | } |
632 | 633 | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 95ef64e4189a..3304caa65347 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -437,7 +437,8 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
437 | */ | 437 | */ |
438 | 438 | ||
439 | saddr->spkt_device[13] = 0; | 439 | saddr->spkt_device[13] = 0; |
440 | dev = dev_get_by_name(sock_net(sk), saddr->spkt_device); | 440 | rcu_read_lock(); |
441 | dev = dev_get_by_name_rcu(sock_net(sk), saddr->spkt_device); | ||
441 | err = -ENODEV; | 442 | err = -ENODEV; |
442 | if (dev == NULL) | 443 | if (dev == NULL) |
443 | goto out_unlock; | 444 | goto out_unlock; |
@@ -500,14 +501,13 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
500 | */ | 501 | */ |
501 | 502 | ||
502 | dev_queue_xmit(skb); | 503 | dev_queue_xmit(skb); |
503 | dev_put(dev); | 504 | rcu_read_unlock(); |
504 | return len; | 505 | return len; |
505 | 506 | ||
506 | out_free: | 507 | out_free: |
507 | kfree_skb(skb); | 508 | kfree_skb(skb); |
508 | out_unlock: | 509 | out_unlock: |
509 | if (dev) | 510 | rcu_read_unlock(); |
510 | dev_put(dev); | ||
511 | return err; | 511 | return err; |
512 | } | 512 | } |
513 | 513 | ||
@@ -1344,7 +1344,8 @@ static struct proto packet_proto = { | |||
1344 | * Create a packet of type SOCK_PACKET. | 1344 | * Create a packet of type SOCK_PACKET. |
1345 | */ | 1345 | */ |
1346 | 1346 | ||
1347 | static int packet_create(struct net *net, struct socket *sock, int protocol) | 1347 | static int packet_create(struct net *net, struct socket *sock, int protocol, |
1348 | int kern) | ||
1348 | { | 1349 | { |
1349 | struct sock *sk; | 1350 | struct sock *sk; |
1350 | struct packet_sock *po; | 1351 | struct packet_sock *po; |
@@ -1518,12 +1519,13 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, | |||
1518 | return -EOPNOTSUPP; | 1519 | return -EOPNOTSUPP; |
1519 | 1520 | ||
1520 | uaddr->sa_family = AF_PACKET; | 1521 | uaddr->sa_family = AF_PACKET; |
1521 | dev = dev_get_by_index(sock_net(sk), pkt_sk(sk)->ifindex); | 1522 | rcu_read_lock(); |
1522 | if (dev) { | 1523 | dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); |
1524 | if (dev) | ||
1523 | strlcpy(uaddr->sa_data, dev->name, 15); | 1525 | strlcpy(uaddr->sa_data, dev->name, 15); |
1524 | dev_put(dev); | 1526 | else |
1525 | } else | ||
1526 | memset(uaddr->sa_data, 0, 14); | 1527 | memset(uaddr->sa_data, 0, 14); |
1528 | rcu_read_unlock(); | ||
1527 | *uaddr_len = sizeof(*uaddr); | 1529 | *uaddr_len = sizeof(*uaddr); |
1528 | 1530 | ||
1529 | return 0; | 1531 | return 0; |
@@ -1543,16 +1545,17 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, | |||
1543 | sll->sll_family = AF_PACKET; | 1545 | sll->sll_family = AF_PACKET; |
1544 | sll->sll_ifindex = po->ifindex; | 1546 | sll->sll_ifindex = po->ifindex; |
1545 | sll->sll_protocol = po->num; | 1547 | sll->sll_protocol = po->num; |
1546 | dev = dev_get_by_index(sock_net(sk), po->ifindex); | 1548 | rcu_read_lock(); |
1549 | dev = dev_get_by_index_rcu(sock_net(sk), po->ifindex); | ||
1547 | if (dev) { | 1550 | if (dev) { |
1548 | sll->sll_hatype = dev->type; | 1551 | sll->sll_hatype = dev->type; |
1549 | sll->sll_halen = dev->addr_len; | 1552 | sll->sll_halen = dev->addr_len; |
1550 | memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len); | 1553 | memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len); |
1551 | dev_put(dev); | ||
1552 | } else { | 1554 | } else { |
1553 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ | 1555 | sll->sll_hatype = 0; /* Bad: we have no ARPHRD_UNSPEC */ |
1554 | sll->sll_halen = 0; | 1556 | sll->sll_halen = 0; |
1555 | } | 1557 | } |
1558 | rcu_read_unlock(); | ||
1556 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; | 1559 | *uaddr_len = offsetof(struct sockaddr_ll, sll_addr) + sll->sll_halen; |
1557 | 1560 | ||
1558 | return 0; | 1561 | return 0; |
diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 66737aa995ea..3bd1be6b26f0 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c | |||
@@ -60,7 +60,8 @@ static inline void phonet_proto_put(struct phonet_protocol *pp) | |||
60 | 60 | ||
61 | /* protocol family functions */ | 61 | /* protocol family functions */ |
62 | 62 | ||
63 | static int pn_socket_create(struct net *net, struct socket *sock, int protocol) | 63 | static int pn_socket_create(struct net *net, struct socket *sock, int protocol, |
64 | int kern) | ||
64 | { | 65 | { |
65 | struct sock *sk; | 66 | struct sock *sk; |
66 | struct pn_sock *pn; | 67 | struct pn_sock *pn; |
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index d8f5d3fb9ee2..609e509b369b 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c | |||
@@ -53,8 +53,7 @@ void phonet_address_notify(int event, struct net_device *dev, u8 addr) | |||
53 | RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); | 53 | RTNLGRP_PHONET_IFADDR, NULL, GFP_KERNEL); |
54 | return; | 54 | return; |
55 | errout: | 55 | errout: |
56 | if (err < 0) | 56 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); |
57 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); | ||
58 | } | 57 | } |
59 | 58 | ||
60 | static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = { | 59 | static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = { |
@@ -212,8 +211,7 @@ void rtm_phonet_notify(int event, struct net_device *dev, u8 dst) | |||
212 | RTNLGRP_PHONET_ROUTE, NULL, GFP_KERNEL); | 211 | RTNLGRP_PHONET_ROUTE, NULL, GFP_KERNEL); |
213 | return; | 212 | return; |
214 | errout: | 213 | errout: |
215 | if (err < 0) | 214 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_ROUTE, err); |
216 | rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_ROUTE, err); | ||
217 | } | 215 | } |
218 | 216 | ||
219 | static const struct nla_policy rtm_phonet_policy[RTA_MAX+1] = { | 217 | static const struct nla_policy rtm_phonet_policy[RTA_MAX+1] = { |
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index a202e5b36079..e25d8d5ce8df 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c | |||
@@ -265,6 +265,9 @@ static int rds_setsockopt(struct socket *sock, int level, int optname, | |||
265 | case RDS_GET_MR: | 265 | case RDS_GET_MR: |
266 | ret = rds_get_mr(rs, optval, optlen); | 266 | ret = rds_get_mr(rs, optval, optlen); |
267 | break; | 267 | break; |
268 | case RDS_GET_MR_FOR_DEST: | ||
269 | ret = rds_get_mr_for_dest(rs, optval, optlen); | ||
270 | break; | ||
268 | case RDS_FREE_MR: | 271 | case RDS_FREE_MR: |
269 | ret = rds_free_mr(rs, optval, optlen); | 272 | ret = rds_free_mr(rs, optval, optlen); |
270 | break; | 273 | break; |
@@ -407,7 +410,8 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol) | |||
407 | return 0; | 410 | return 0; |
408 | } | 411 | } |
409 | 412 | ||
410 | static int rds_create(struct net *net, struct socket *sock, int protocol) | 413 | static int rds_create(struct net *net, struct socket *sock, int protocol, |
414 | int kern) | ||
411 | { | 415 | { |
412 | struct sock *sk; | 416 | struct sock *sk; |
413 | 417 | ||
diff --git a/net/rds/cong.c b/net/rds/cong.c index dd2711df640b..6d06cac2649c 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c | |||
@@ -218,6 +218,8 @@ void rds_cong_queue_updates(struct rds_cong_map *map) | |||
218 | spin_lock_irqsave(&rds_cong_lock, flags); | 218 | spin_lock_irqsave(&rds_cong_lock, flags); |
219 | 219 | ||
220 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { | 220 | list_for_each_entry(conn, &map->m_conn_list, c_map_item) { |
221 | if (conn->c_loopback) | ||
222 | continue; | ||
221 | if (!test_and_set_bit(0, &conn->c_map_queued)) { | 223 | if (!test_and_set_bit(0, &conn->c_map_queued)) { |
222 | rds_stats_inc(s_cong_update_queued); | 224 | rds_stats_inc(s_cong_update_queued); |
223 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 225 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); |
diff --git a/net/rds/ib.h b/net/rds/ib.h index 1378b854cac0..64df4e79b29f 100644 --- a/net/rds/ib.h +++ b/net/rds/ib.h | |||
@@ -98,6 +98,7 @@ struct rds_ib_connection { | |||
98 | struct rds_ib_send_work *i_sends; | 98 | struct rds_ib_send_work *i_sends; |
99 | 99 | ||
100 | /* rx */ | 100 | /* rx */ |
101 | struct tasklet_struct i_recv_tasklet; | ||
101 | struct mutex i_recv_mutex; | 102 | struct mutex i_recv_mutex; |
102 | struct rds_ib_work_ring i_recv_ring; | 103 | struct rds_ib_work_ring i_recv_ring; |
103 | struct rds_ib_incoming *i_ibinc; | 104 | struct rds_ib_incoming *i_ibinc; |
@@ -303,6 +304,7 @@ void rds_ib_inc_free(struct rds_incoming *inc); | |||
303 | int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, | 304 | int rds_ib_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, |
304 | size_t size); | 305 | size_t size); |
305 | void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context); | 306 | void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context); |
307 | void rds_ib_recv_tasklet_fn(unsigned long data); | ||
306 | void rds_ib_recv_init_ring(struct rds_ib_connection *ic); | 308 | void rds_ib_recv_init_ring(struct rds_ib_connection *ic); |
307 | void rds_ib_recv_clear_ring(struct rds_ib_connection *ic); | 309 | void rds_ib_recv_clear_ring(struct rds_ib_connection *ic); |
308 | void rds_ib_recv_init_ack(struct rds_ib_connection *ic); | 310 | void rds_ib_recv_init_ack(struct rds_ib_connection *ic); |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index c2d372f13dbb..9d320692a4fc 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
@@ -694,6 +694,8 @@ int rds_ib_conn_alloc(struct rds_connection *conn, gfp_t gfp) | |||
694 | return -ENOMEM; | 694 | return -ENOMEM; |
695 | 695 | ||
696 | INIT_LIST_HEAD(&ic->ib_node); | 696 | INIT_LIST_HEAD(&ic->ib_node); |
697 | tasklet_init(&ic->i_recv_tasklet, rds_ib_recv_tasklet_fn, | ||
698 | (unsigned long) ic); | ||
697 | mutex_init(&ic->i_recv_mutex); | 699 | mutex_init(&ic->i_recv_mutex); |
698 | #ifndef KERNEL_HAS_ATOMIC64 | 700 | #ifndef KERNEL_HAS_ATOMIC64 |
699 | spin_lock_init(&ic->i_ack_lock); | 701 | spin_lock_init(&ic->i_ack_lock); |
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index ef3ab5b7283e..c5e916598c14 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c | |||
@@ -187,11 +187,8 @@ void __rds_ib_destroy_conns(struct list_head *list, spinlock_t *list_lock) | |||
187 | INIT_LIST_HEAD(list); | 187 | INIT_LIST_HEAD(list); |
188 | spin_unlock_irq(list_lock); | 188 | spin_unlock_irq(list_lock); |
189 | 189 | ||
190 | list_for_each_entry_safe(ic, _ic, &tmp_list, ib_node) { | 190 | list_for_each_entry_safe(ic, _ic, &tmp_list, ib_node) |
191 | if (ic->conn->c_passive) | ||
192 | rds_conn_destroy(ic->conn->c_passive); | ||
193 | rds_conn_destroy(ic->conn); | 191 | rds_conn_destroy(ic->conn); |
194 | } | ||
195 | } | 192 | } |
196 | 193 | ||
197 | struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_ibdev) | 194 | struct rds_ib_mr_pool *rds_ib_create_mr_pool(struct rds_ib_device *rds_ibdev) |
diff --git a/net/rds/ib_recv.c b/net/rds/ib_recv.c index cd7a6cfcab03..fe5ab8c6b964 100644 --- a/net/rds/ib_recv.c +++ b/net/rds/ib_recv.c | |||
@@ -143,15 +143,16 @@ static int rds_ib_recv_refill_one(struct rds_connection *conn, | |||
143 | int ret = -ENOMEM; | 143 | int ret = -ENOMEM; |
144 | 144 | ||
145 | if (recv->r_ibinc == NULL) { | 145 | if (recv->r_ibinc == NULL) { |
146 | if (atomic_read(&rds_ib_allocation) >= rds_ib_sysctl_max_recv_allocation) { | 146 | if (!atomic_add_unless(&rds_ib_allocation, 1, rds_ib_sysctl_max_recv_allocation)) { |
147 | rds_ib_stats_inc(s_ib_rx_alloc_limit); | 147 | rds_ib_stats_inc(s_ib_rx_alloc_limit); |
148 | goto out; | 148 | goto out; |
149 | } | 149 | } |
150 | recv->r_ibinc = kmem_cache_alloc(rds_ib_incoming_slab, | 150 | recv->r_ibinc = kmem_cache_alloc(rds_ib_incoming_slab, |
151 | kptr_gfp); | 151 | kptr_gfp); |
152 | if (recv->r_ibinc == NULL) | 152 | if (recv->r_ibinc == NULL) { |
153 | atomic_dec(&rds_ib_allocation); | ||
153 | goto out; | 154 | goto out; |
154 | atomic_inc(&rds_ib_allocation); | 155 | } |
155 | INIT_LIST_HEAD(&recv->r_ibinc->ii_frags); | 156 | INIT_LIST_HEAD(&recv->r_ibinc->ii_frags); |
156 | rds_inc_init(&recv->r_ibinc->ii_inc, conn, conn->c_faddr); | 157 | rds_inc_init(&recv->r_ibinc->ii_inc, conn, conn->c_faddr); |
157 | } | 158 | } |
@@ -824,17 +825,22 @@ void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
824 | { | 825 | { |
825 | struct rds_connection *conn = context; | 826 | struct rds_connection *conn = context; |
826 | struct rds_ib_connection *ic = conn->c_transport_data; | 827 | struct rds_ib_connection *ic = conn->c_transport_data; |
827 | struct ib_wc wc; | ||
828 | struct rds_ib_ack_state state = { 0, }; | ||
829 | struct rds_ib_recv_work *recv; | ||
830 | 828 | ||
831 | rdsdebug("conn %p cq %p\n", conn, cq); | 829 | rdsdebug("conn %p cq %p\n", conn, cq); |
832 | 830 | ||
833 | rds_ib_stats_inc(s_ib_rx_cq_call); | 831 | rds_ib_stats_inc(s_ib_rx_cq_call); |
834 | 832 | ||
835 | ib_req_notify_cq(cq, IB_CQ_SOLICITED); | 833 | tasklet_schedule(&ic->i_recv_tasklet); |
834 | } | ||
835 | |||
836 | static inline void rds_poll_cq(struct rds_ib_connection *ic, | ||
837 | struct rds_ib_ack_state *state) | ||
838 | { | ||
839 | struct rds_connection *conn = ic->conn; | ||
840 | struct ib_wc wc; | ||
841 | struct rds_ib_recv_work *recv; | ||
836 | 842 | ||
837 | while (ib_poll_cq(cq, 1, &wc) > 0) { | 843 | while (ib_poll_cq(ic->i_recv_cq, 1, &wc) > 0) { |
838 | rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", | 844 | rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", |
839 | (unsigned long long)wc.wr_id, wc.status, wc.byte_len, | 845 | (unsigned long long)wc.wr_id, wc.status, wc.byte_len, |
840 | be32_to_cpu(wc.ex.imm_data)); | 846 | be32_to_cpu(wc.ex.imm_data)); |
@@ -852,7 +858,7 @@ void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
852 | if (rds_conn_up(conn) || rds_conn_connecting(conn)) { | 858 | if (rds_conn_up(conn) || rds_conn_connecting(conn)) { |
853 | /* We expect errors as the qp is drained during shutdown */ | 859 | /* We expect errors as the qp is drained during shutdown */ |
854 | if (wc.status == IB_WC_SUCCESS) { | 860 | if (wc.status == IB_WC_SUCCESS) { |
855 | rds_ib_process_recv(conn, recv, wc.byte_len, &state); | 861 | rds_ib_process_recv(conn, recv, wc.byte_len, state); |
856 | } else { | 862 | } else { |
857 | rds_ib_conn_error(conn, "recv completion on " | 863 | rds_ib_conn_error(conn, "recv completion on " |
858 | "%pI4 had status %u, disconnecting and " | 864 | "%pI4 had status %u, disconnecting and " |
@@ -863,6 +869,17 @@ void rds_ib_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
863 | 869 | ||
864 | rds_ib_ring_free(&ic->i_recv_ring, 1); | 870 | rds_ib_ring_free(&ic->i_recv_ring, 1); |
865 | } | 871 | } |
872 | } | ||
873 | |||
874 | void rds_ib_recv_tasklet_fn(unsigned long data) | ||
875 | { | ||
876 | struct rds_ib_connection *ic = (struct rds_ib_connection *) data; | ||
877 | struct rds_connection *conn = ic->conn; | ||
878 | struct rds_ib_ack_state state = { 0, }; | ||
879 | |||
880 | rds_poll_cq(ic, &state); | ||
881 | ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); | ||
882 | rds_poll_cq(ic, &state); | ||
866 | 883 | ||
867 | if (state.ack_next_valid) | 884 | if (state.ack_next_valid) |
868 | rds_ib_set_ack(ic, state.ack_next, state.ack_required); | 885 | rds_ib_set_ack(ic, state.ack_next, state.ack_required); |
diff --git a/net/rds/iw.h b/net/rds/iw.h index dd72b62bd506..eef2f0c28476 100644 --- a/net/rds/iw.h +++ b/net/rds/iw.h | |||
@@ -119,6 +119,7 @@ struct rds_iw_connection { | |||
119 | struct rds_iw_send_work *i_sends; | 119 | struct rds_iw_send_work *i_sends; |
120 | 120 | ||
121 | /* rx */ | 121 | /* rx */ |
122 | struct tasklet_struct i_recv_tasklet; | ||
122 | struct mutex i_recv_mutex; | 123 | struct mutex i_recv_mutex; |
123 | struct rds_iw_work_ring i_recv_ring; | 124 | struct rds_iw_work_ring i_recv_ring; |
124 | struct rds_iw_incoming *i_iwinc; | 125 | struct rds_iw_incoming *i_iwinc; |
@@ -330,6 +331,7 @@ void rds_iw_inc_free(struct rds_incoming *inc); | |||
330 | int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, | 331 | int rds_iw_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, |
331 | size_t size); | 332 | size_t size); |
332 | void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context); | 333 | void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context); |
334 | void rds_iw_recv_tasklet_fn(unsigned long data); | ||
333 | void rds_iw_recv_init_ring(struct rds_iw_connection *ic); | 335 | void rds_iw_recv_init_ring(struct rds_iw_connection *ic); |
334 | void rds_iw_recv_clear_ring(struct rds_iw_connection *ic); | 336 | void rds_iw_recv_clear_ring(struct rds_iw_connection *ic); |
335 | void rds_iw_recv_init_ack(struct rds_iw_connection *ic); | 337 | void rds_iw_recv_init_ack(struct rds_iw_connection *ic); |
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index a416b0d492b1..394cf6b4d0aa 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c | |||
@@ -696,6 +696,8 @@ int rds_iw_conn_alloc(struct rds_connection *conn, gfp_t gfp) | |||
696 | return -ENOMEM; | 696 | return -ENOMEM; |
697 | 697 | ||
698 | INIT_LIST_HEAD(&ic->iw_node); | 698 | INIT_LIST_HEAD(&ic->iw_node); |
699 | tasklet_init(&ic->i_recv_tasklet, rds_iw_recv_tasklet_fn, | ||
700 | (unsigned long) ic); | ||
699 | mutex_init(&ic->i_recv_mutex); | 701 | mutex_init(&ic->i_recv_mutex); |
700 | #ifndef KERNEL_HAS_ATOMIC64 | 702 | #ifndef KERNEL_HAS_ATOMIC64 |
701 | spin_lock_init(&ic->i_ack_lock); | 703 | spin_lock_init(&ic->i_ack_lock); |
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index de4a1b16bf7b..b25d785e49fc 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c | |||
@@ -245,11 +245,8 @@ void __rds_iw_destroy_conns(struct list_head *list, spinlock_t *list_lock) | |||
245 | INIT_LIST_HEAD(list); | 245 | INIT_LIST_HEAD(list); |
246 | spin_unlock_irq(list_lock); | 246 | spin_unlock_irq(list_lock); |
247 | 247 | ||
248 | list_for_each_entry_safe(ic, _ic, &tmp_list, iw_node) { | 248 | list_for_each_entry_safe(ic, _ic, &tmp_list, iw_node) |
249 | if (ic->conn->c_passive) | ||
250 | rds_conn_destroy(ic->conn->c_passive); | ||
251 | rds_conn_destroy(ic->conn); | 249 | rds_conn_destroy(ic->conn); |
252 | } | ||
253 | } | 250 | } |
254 | 251 | ||
255 | static void rds_iw_set_scatterlist(struct rds_iw_scatterlist *sg, | 252 | static void rds_iw_set_scatterlist(struct rds_iw_scatterlist *sg, |
diff --git a/net/rds/iw_recv.c b/net/rds/iw_recv.c index 8683f5f66c4b..24fc53f03833 100644 --- a/net/rds/iw_recv.c +++ b/net/rds/iw_recv.c | |||
@@ -143,15 +143,16 @@ static int rds_iw_recv_refill_one(struct rds_connection *conn, | |||
143 | int ret = -ENOMEM; | 143 | int ret = -ENOMEM; |
144 | 144 | ||
145 | if (recv->r_iwinc == NULL) { | 145 | if (recv->r_iwinc == NULL) { |
146 | if (atomic_read(&rds_iw_allocation) >= rds_iw_sysctl_max_recv_allocation) { | 146 | if (!atomic_add_unless(&rds_iw_allocation, 1, rds_iw_sysctl_max_recv_allocation)) { |
147 | rds_iw_stats_inc(s_iw_rx_alloc_limit); | 147 | rds_iw_stats_inc(s_iw_rx_alloc_limit); |
148 | goto out; | 148 | goto out; |
149 | } | 149 | } |
150 | recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab, | 150 | recv->r_iwinc = kmem_cache_alloc(rds_iw_incoming_slab, |
151 | kptr_gfp); | 151 | kptr_gfp); |
152 | if (recv->r_iwinc == NULL) | 152 | if (recv->r_iwinc == NULL) { |
153 | atomic_dec(&rds_iw_allocation); | ||
153 | goto out; | 154 | goto out; |
154 | atomic_inc(&rds_iw_allocation); | 155 | } |
155 | INIT_LIST_HEAD(&recv->r_iwinc->ii_frags); | 156 | INIT_LIST_HEAD(&recv->r_iwinc->ii_frags); |
156 | rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr); | 157 | rds_inc_init(&recv->r_iwinc->ii_inc, conn, conn->c_faddr); |
157 | } | 158 | } |
@@ -783,17 +784,22 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
783 | { | 784 | { |
784 | struct rds_connection *conn = context; | 785 | struct rds_connection *conn = context; |
785 | struct rds_iw_connection *ic = conn->c_transport_data; | 786 | struct rds_iw_connection *ic = conn->c_transport_data; |
786 | struct ib_wc wc; | ||
787 | struct rds_iw_ack_state state = { 0, }; | ||
788 | struct rds_iw_recv_work *recv; | ||
789 | 787 | ||
790 | rdsdebug("conn %p cq %p\n", conn, cq); | 788 | rdsdebug("conn %p cq %p\n", conn, cq); |
791 | 789 | ||
792 | rds_iw_stats_inc(s_iw_rx_cq_call); | 790 | rds_iw_stats_inc(s_iw_rx_cq_call); |
793 | 791 | ||
794 | ib_req_notify_cq(cq, IB_CQ_SOLICITED); | 792 | tasklet_schedule(&ic->i_recv_tasklet); |
793 | } | ||
794 | |||
795 | static inline void rds_poll_cq(struct rds_iw_connection *ic, | ||
796 | struct rds_iw_ack_state *state) | ||
797 | { | ||
798 | struct rds_connection *conn = ic->conn; | ||
799 | struct ib_wc wc; | ||
800 | struct rds_iw_recv_work *recv; | ||
795 | 801 | ||
796 | while (ib_poll_cq(cq, 1, &wc) > 0) { | 802 | while (ib_poll_cq(ic->i_recv_cq, 1, &wc) > 0) { |
797 | rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", | 803 | rdsdebug("wc wr_id 0x%llx status %u byte_len %u imm_data %u\n", |
798 | (unsigned long long)wc.wr_id, wc.status, wc.byte_len, | 804 | (unsigned long long)wc.wr_id, wc.status, wc.byte_len, |
799 | be32_to_cpu(wc.ex.imm_data)); | 805 | be32_to_cpu(wc.ex.imm_data)); |
@@ -811,7 +817,7 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
811 | if (rds_conn_up(conn) || rds_conn_connecting(conn)) { | 817 | if (rds_conn_up(conn) || rds_conn_connecting(conn)) { |
812 | /* We expect errors as the qp is drained during shutdown */ | 818 | /* We expect errors as the qp is drained during shutdown */ |
813 | if (wc.status == IB_WC_SUCCESS) { | 819 | if (wc.status == IB_WC_SUCCESS) { |
814 | rds_iw_process_recv(conn, recv, wc.byte_len, &state); | 820 | rds_iw_process_recv(conn, recv, wc.byte_len, state); |
815 | } else { | 821 | } else { |
816 | rds_iw_conn_error(conn, "recv completion on " | 822 | rds_iw_conn_error(conn, "recv completion on " |
817 | "%pI4 had status %u, disconnecting and " | 823 | "%pI4 had status %u, disconnecting and " |
@@ -822,6 +828,17 @@ void rds_iw_recv_cq_comp_handler(struct ib_cq *cq, void *context) | |||
822 | 828 | ||
823 | rds_iw_ring_free(&ic->i_recv_ring, 1); | 829 | rds_iw_ring_free(&ic->i_recv_ring, 1); |
824 | } | 830 | } |
831 | } | ||
832 | |||
833 | void rds_iw_recv_tasklet_fn(unsigned long data) | ||
834 | { | ||
835 | struct rds_iw_connection *ic = (struct rds_iw_connection *) data; | ||
836 | struct rds_connection *conn = ic->conn; | ||
837 | struct rds_iw_ack_state state = { 0, }; | ||
838 | |||
839 | rds_poll_cq(ic, &state); | ||
840 | ib_req_notify_cq(ic->i_recv_cq, IB_CQ_SOLICITED); | ||
841 | rds_poll_cq(ic, &state); | ||
825 | 842 | ||
826 | if (state.ack_next_valid) | 843 | if (state.ack_next_valid) |
827 | rds_iw_set_ack(ic, state.ack_next, state.ack_required); | 844 | rds_iw_set_ack(ic, state.ack_next, state.ack_required); |
diff --git a/net/rds/rdma.c b/net/rds/rdma.c index 8dc83d2caa58..971b5a668458 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c | |||
@@ -317,6 +317,30 @@ int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen) | |||
317 | return __rds_rdma_map(rs, &args, NULL, NULL); | 317 | return __rds_rdma_map(rs, &args, NULL, NULL); |
318 | } | 318 | } |
319 | 319 | ||
320 | int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen) | ||
321 | { | ||
322 | struct rds_get_mr_for_dest_args args; | ||
323 | struct rds_get_mr_args new_args; | ||
324 | |||
325 | if (optlen != sizeof(struct rds_get_mr_for_dest_args)) | ||
326 | return -EINVAL; | ||
327 | |||
328 | if (copy_from_user(&args, (struct rds_get_mr_for_dest_args __user *)optval, | ||
329 | sizeof(struct rds_get_mr_for_dest_args))) | ||
330 | return -EFAULT; | ||
331 | |||
332 | /* | ||
333 | * Initially, just behave like get_mr(). | ||
334 | * TODO: Implement get_mr as wrapper around this | ||
335 | * and deprecate it. | ||
336 | */ | ||
337 | new_args.vec = args.vec; | ||
338 | new_args.cookie_addr = args.cookie_addr; | ||
339 | new_args.flags = args.flags; | ||
340 | |||
341 | return __rds_rdma_map(rs, &new_args, NULL, NULL); | ||
342 | } | ||
343 | |||
320 | /* | 344 | /* |
321 | * Free the MR indicated by the given R_Key | 345 | * Free the MR indicated by the given R_Key |
322 | */ | 346 | */ |
diff --git a/net/rds/rdma.h b/net/rds/rdma.h index 425512098b0b..909c39835a5d 100644 --- a/net/rds/rdma.h +++ b/net/rds/rdma.h | |||
@@ -61,6 +61,7 @@ static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen); | 63 | int rds_get_mr(struct rds_sock *rs, char __user *optval, int optlen); |
64 | int rds_get_mr_for_dest(struct rds_sock *rs, char __user *optval, int optlen); | ||
64 | int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen); | 65 | int rds_free_mr(struct rds_sock *rs, char __user *optval, int optlen); |
65 | void rds_rdma_drop_keys(struct rds_sock *rs); | 66 | void rds_rdma_drop_keys(struct rds_sock *rs); |
66 | int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, | 67 | int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm, |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index c17734c2ce89..4de4287fec37 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -512,7 +512,8 @@ static struct proto rose_proto = { | |||
512 | .obj_size = sizeof(struct rose_sock), | 512 | .obj_size = sizeof(struct rose_sock), |
513 | }; | 513 | }; |
514 | 514 | ||
515 | static int rose_create(struct net *net, struct socket *sock, int protocol) | 515 | static int rose_create(struct net *net, struct socket *sock, int protocol, |
516 | int kern) | ||
516 | { | 517 | { |
517 | struct sock *sk; | 518 | struct sock *sk; |
518 | struct rose_sock *rose; | 519 | struct rose_sock *rose; |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 9478d9b3d977..ea2e72337e2f 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -578,18 +578,18 @@ static int rose_clear_routes(void) | |||
578 | 578 | ||
579 | /* | 579 | /* |
580 | * Check that the device given is a valid AX.25 interface that is "up". | 580 | * Check that the device given is a valid AX.25 interface that is "up". |
581 | * called whith RTNL | ||
581 | */ | 582 | */ |
582 | static struct net_device *rose_ax25_dev_get(char *devname) | 583 | static struct net_device *rose_ax25_dev_find(char *devname) |
583 | { | 584 | { |
584 | struct net_device *dev; | 585 | struct net_device *dev; |
585 | 586 | ||
586 | if ((dev = dev_get_by_name(&init_net, devname)) == NULL) | 587 | if ((dev = __dev_get_by_name(&init_net, devname)) == NULL) |
587 | return NULL; | 588 | return NULL; |
588 | 589 | ||
589 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) | 590 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25) |
590 | return dev; | 591 | return dev; |
591 | 592 | ||
592 | dev_put(dev); | ||
593 | return NULL; | 593 | return NULL; |
594 | } | 594 | } |
595 | 595 | ||
@@ -600,13 +600,13 @@ struct net_device *rose_dev_first(void) | |||
600 | { | 600 | { |
601 | struct net_device *dev, *first = NULL; | 601 | struct net_device *dev, *first = NULL; |
602 | 602 | ||
603 | read_lock(&dev_base_lock); | 603 | rcu_read_lock(); |
604 | for_each_netdev(&init_net, dev) { | 604 | for_each_netdev_rcu(&init_net, dev) { |
605 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE) | 605 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE) |
606 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) | 606 | if (first == NULL || strncmp(dev->name, first->name, 3) < 0) |
607 | first = dev; | 607 | first = dev; |
608 | } | 608 | } |
609 | read_unlock(&dev_base_lock); | 609 | rcu_read_unlock(); |
610 | 610 | ||
611 | return first; | 611 | return first; |
612 | } | 612 | } |
@@ -618,8 +618,8 @@ struct net_device *rose_dev_get(rose_address *addr) | |||
618 | { | 618 | { |
619 | struct net_device *dev; | 619 | struct net_device *dev; |
620 | 620 | ||
621 | read_lock(&dev_base_lock); | 621 | rcu_read_lock(); |
622 | for_each_netdev(&init_net, dev) { | 622 | for_each_netdev_rcu(&init_net, dev) { |
623 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) { | 623 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) { |
624 | dev_hold(dev); | 624 | dev_hold(dev); |
625 | goto out; | 625 | goto out; |
@@ -627,7 +627,7 @@ struct net_device *rose_dev_get(rose_address *addr) | |||
627 | } | 627 | } |
628 | dev = NULL; | 628 | dev = NULL; |
629 | out: | 629 | out: |
630 | read_unlock(&dev_base_lock); | 630 | rcu_read_unlock(); |
631 | return dev; | 631 | return dev; |
632 | } | 632 | } |
633 | 633 | ||
@@ -635,14 +635,14 @@ static int rose_dev_exists(rose_address *addr) | |||
635 | { | 635 | { |
636 | struct net_device *dev; | 636 | struct net_device *dev; |
637 | 637 | ||
638 | read_lock(&dev_base_lock); | 638 | rcu_read_lock(); |
639 | for_each_netdev(&init_net, dev) { | 639 | for_each_netdev_rcu(&init_net, dev) { |
640 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) | 640 | if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) |
641 | goto out; | 641 | goto out; |
642 | } | 642 | } |
643 | dev = NULL; | 643 | dev = NULL; |
644 | out: | 644 | out: |
645 | read_unlock(&dev_base_lock); | 645 | rcu_read_unlock(); |
646 | return dev != NULL; | 646 | return dev != NULL; |
647 | } | 647 | } |
648 | 648 | ||
@@ -720,27 +720,23 @@ int rose_rt_ioctl(unsigned int cmd, void __user *arg) | |||
720 | case SIOCADDRT: | 720 | case SIOCADDRT: |
721 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) | 721 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) |
722 | return -EFAULT; | 722 | return -EFAULT; |
723 | if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) | 723 | if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) |
724 | return -EINVAL; | 724 | return -EINVAL; |
725 | if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */ | 725 | if (rose_dev_exists(&rose_route.address)) /* Can't add routes to ourself */ |
726 | dev_put(dev); | ||
727 | return -EINVAL; | 726 | return -EINVAL; |
728 | } | ||
729 | if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ | 727 | if (rose_route.mask > 10) /* Mask can't be more than 10 digits */ |
730 | return -EINVAL; | 728 | return -EINVAL; |
731 | if (rose_route.ndigis > AX25_MAX_DIGIS) | 729 | if (rose_route.ndigis > AX25_MAX_DIGIS) |
732 | return -EINVAL; | 730 | return -EINVAL; |
733 | err = rose_add_node(&rose_route, dev); | 731 | err = rose_add_node(&rose_route, dev); |
734 | dev_put(dev); | ||
735 | return err; | 732 | return err; |
736 | 733 | ||
737 | case SIOCDELRT: | 734 | case SIOCDELRT: |
738 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) | 735 | if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct))) |
739 | return -EFAULT; | 736 | return -EFAULT; |
740 | if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL) | 737 | if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL) |
741 | return -EINVAL; | 738 | return -EINVAL; |
742 | err = rose_del_node(&rose_route, dev); | 739 | err = rose_del_node(&rose_route, dev); |
743 | dev_put(dev); | ||
744 | return err; | 740 | return err; |
745 | 741 | ||
746 | case SIOCRSCLRRT: | 742 | case SIOCRSCLRRT: |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 6817c9781ef3..f978d02a248a 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -608,7 +608,8 @@ static unsigned int rxrpc_poll(struct file *file, struct socket *sock, | |||
608 | /* | 608 | /* |
609 | * create an RxRPC socket | 609 | * create an RxRPC socket |
610 | */ | 610 | */ |
611 | static int rxrpc_create(struct net *net, struct socket *sock, int protocol) | 611 | static int rxrpc_create(struct net *net, struct socket *sock, int protocol, |
612 | int kern) | ||
612 | { | 613 | { |
613 | struct rxrpc_sock *rx; | 614 | struct rxrpc_sock *rx; |
614 | struct sock *sk; | 615 | struct sock *sk; |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 7cf6c0fbc7a6..c024da77824f 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -404,6 +404,7 @@ static int tcf_node_dump(struct tcf_proto *tp, unsigned long n, | |||
404 | a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER); | 404 | a->cb->nlh->nlmsg_seq, NLM_F_MULTI, RTM_NEWTFILTER); |
405 | } | 405 | } |
406 | 406 | ||
407 | /* called with RTNL */ | ||
407 | static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | 408 | static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) |
408 | { | 409 | { |
409 | struct net *net = sock_net(skb->sk); | 410 | struct net *net = sock_net(skb->sk); |
@@ -422,7 +423,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb) | |||
422 | 423 | ||
423 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) | 424 | if (cb->nlh->nlmsg_len < NLMSG_LENGTH(sizeof(*tcm))) |
424 | return skb->len; | 425 | return skb->len; |
425 | if ((dev = dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) | 426 | if ((dev = __dev_get_by_index(&init_net, tcm->tcm_ifindex)) == NULL) |
426 | return skb->len; | 427 | return skb->len; |
427 | 428 | ||
428 | if (!tcm->tcm_parent) | 429 | if (!tcm->tcm_parent) |
@@ -484,7 +485,6 @@ errout: | |||
484 | if (cl) | 485 | if (cl) |
485 | cops->put(q, cl); | 486 | cops->put(q, cl); |
486 | out: | 487 | out: |
487 | dev_put(dev); | ||
488 | return skb->len; | 488 | return skb->len; |
489 | } | 489 | } |
490 | 490 | ||
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index 18d85d259104..8e8d836f00c0 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -303,17 +303,17 @@ META_COLLECTOR(var_sk_bound_if) | |||
303 | { | 303 | { |
304 | SKIP_NONLOCAL(skb); | 304 | SKIP_NONLOCAL(skb); |
305 | 305 | ||
306 | if (skb->sk->sk_bound_dev_if == 0) { | 306 | if (skb->sk->sk_bound_dev_if == 0) { |
307 | dst->value = (unsigned long) "any"; | 307 | dst->value = (unsigned long) "any"; |
308 | dst->len = 3; | 308 | dst->len = 3; |
309 | } else { | 309 | } else { |
310 | struct net_device *dev; | 310 | struct net_device *dev; |
311 | 311 | ||
312 | dev = dev_get_by_index(&init_net, skb->sk->sk_bound_dev_if); | 312 | rcu_read_lock(); |
313 | dev = dev_get_by_index_rcu(&init_net, skb->sk->sk_bound_dev_if); | ||
313 | *err = var_dev(dev, dst); | 314 | *err = var_dev(dev, dst); |
314 | if (dev) | 315 | rcu_read_unlock(); |
315 | dev_put(dev); | 316 | } |
316 | } | ||
317 | } | 317 | } |
318 | 318 | ||
319 | META_COLLECTOR(int_sk_refcnt) | 319 | META_COLLECTOR(int_sk_refcnt) |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index bb280e60e00a..cc50fbe99291 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -837,15 +837,16 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
837 | if (type & IPV6_ADDR_LINKLOCAL) { | 837 | if (type & IPV6_ADDR_LINKLOCAL) { |
838 | if (!addr->v6.sin6_scope_id) | 838 | if (!addr->v6.sin6_scope_id) |
839 | return 0; | 839 | return 0; |
840 | dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); | 840 | rcu_read_lock(); |
841 | if (!dev) | 841 | dev = dev_get_by_index_rcu(&init_net, |
842 | return 0; | 842 | addr->v6.sin6_scope_id); |
843 | if (!ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, | 843 | if (!dev || |
844 | !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, | ||
844 | dev, 0)) { | 845 | dev, 0)) { |
845 | dev_put(dev); | 846 | rcu_read_unlock(); |
846 | return 0; | 847 | return 0; |
847 | } | 848 | } |
848 | dev_put(dev); | 849 | rcu_read_unlock(); |
849 | } else if (type == IPV6_ADDR_MAPPED) { | 850 | } else if (type == IPV6_ADDR_MAPPED) { |
850 | if (!opt->v4mapped) | 851 | if (!opt->v4mapped) |
851 | return 0; | 852 | return 0; |
@@ -873,10 +874,12 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
873 | if (type & IPV6_ADDR_LINKLOCAL) { | 874 | if (type & IPV6_ADDR_LINKLOCAL) { |
874 | if (!addr->v6.sin6_scope_id) | 875 | if (!addr->v6.sin6_scope_id) |
875 | return 0; | 876 | return 0; |
876 | dev = dev_get_by_index(&init_net, addr->v6.sin6_scope_id); | 877 | rcu_read_lock(); |
878 | dev = dev_get_by_index_rcu(&init_net, | ||
879 | addr->v6.sin6_scope_id); | ||
880 | rcu_read_unlock(); | ||
877 | if (!dev) | 881 | if (!dev) |
878 | return 0; | 882 | return 0; |
879 | dev_put(dev); | ||
880 | } | 883 | } |
881 | af = opt->pf->af; | 884 | af = opt->pf->af; |
882 | } | 885 | } |
@@ -930,7 +933,6 @@ static struct inet_protosw sctpv6_seqpacket_protosw = { | |||
930 | .protocol = IPPROTO_SCTP, | 933 | .protocol = IPPROTO_SCTP, |
931 | .prot = &sctpv6_prot, | 934 | .prot = &sctpv6_prot, |
932 | .ops = &inet6_seqpacket_ops, | 935 | .ops = &inet6_seqpacket_ops, |
933 | .capability = -1, | ||
934 | .no_check = 0, | 936 | .no_check = 0, |
935 | .flags = SCTP_PROTOSW_FLAG | 937 | .flags = SCTP_PROTOSW_FLAG |
936 | }; | 938 | }; |
@@ -939,7 +941,6 @@ static struct inet_protosw sctpv6_stream_protosw = { | |||
939 | .protocol = IPPROTO_SCTP, | 941 | .protocol = IPPROTO_SCTP, |
940 | .prot = &sctpv6_prot, | 942 | .prot = &sctpv6_prot, |
941 | .ops = &inet6_seqpacket_ops, | 943 | .ops = &inet6_seqpacket_ops, |
942 | .capability = -1, | ||
943 | .no_check = 0, | 944 | .no_check = 0, |
944 | .flags = SCTP_PROTOSW_FLAG, | 945 | .flags = SCTP_PROTOSW_FLAG, |
945 | }; | 946 | }; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d9f4cc2c7869..08ef203d36ac 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -205,14 +205,14 @@ static void sctp_get_local_addr_list(void) | |||
205 | struct list_head *pos; | 205 | struct list_head *pos; |
206 | struct sctp_af *af; | 206 | struct sctp_af *af; |
207 | 207 | ||
208 | read_lock(&dev_base_lock); | 208 | rcu_read_lock(); |
209 | for_each_netdev(&init_net, dev) { | 209 | for_each_netdev_rcu(&init_net, dev) { |
210 | __list_for_each(pos, &sctp_address_families) { | 210 | __list_for_each(pos, &sctp_address_families) { |
211 | af = list_entry(pos, struct sctp_af, list); | 211 | af = list_entry(pos, struct sctp_af, list); |
212 | af->copy_addrlist(&sctp_local_addr_list, dev); | 212 | af->copy_addrlist(&sctp_local_addr_list, dev); |
213 | } | 213 | } |
214 | } | 214 | } |
215 | read_unlock(&dev_base_lock); | 215 | rcu_read_unlock(); |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Free the existing local addresses. */ | 218 | /* Free the existing local addresses. */ |
@@ -909,7 +909,6 @@ static struct inet_protosw sctp_seqpacket_protosw = { | |||
909 | .protocol = IPPROTO_SCTP, | 909 | .protocol = IPPROTO_SCTP, |
910 | .prot = &sctp_prot, | 910 | .prot = &sctp_prot, |
911 | .ops = &inet_seqpacket_ops, | 911 | .ops = &inet_seqpacket_ops, |
912 | .capability = -1, | ||
913 | .no_check = 0, | 912 | .no_check = 0, |
914 | .flags = SCTP_PROTOSW_FLAG | 913 | .flags = SCTP_PROTOSW_FLAG |
915 | }; | 914 | }; |
@@ -918,7 +917,6 @@ static struct inet_protosw sctp_stream_protosw = { | |||
918 | .protocol = IPPROTO_SCTP, | 917 | .protocol = IPPROTO_SCTP, |
919 | .prot = &sctp_prot, | 918 | .prot = &sctp_prot, |
920 | .ops = &inet_seqpacket_ops, | 919 | .ops = &inet_seqpacket_ops, |
921 | .capability = -1, | ||
922 | .no_check = 0, | 920 | .no_check = 0, |
923 | .flags = SCTP_PROTOSW_FLAG | 921 | .flags = SCTP_PROTOSW_FLAG |
924 | }; | 922 | }; |
diff --git a/net/socket.c b/net/socket.c index 9dff31c9b799..befd9f5b1620 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -97,6 +97,20 @@ | |||
97 | #include <net/sock.h> | 97 | #include <net/sock.h> |
98 | #include <linux/netfilter.h> | 98 | #include <linux/netfilter.h> |
99 | 99 | ||
100 | #include <linux/if_tun.h> | ||
101 | #include <linux/ipv6_route.h> | ||
102 | #include <linux/route.h> | ||
103 | #include <linux/atmdev.h> | ||
104 | #include <linux/atmarp.h> | ||
105 | #include <linux/atmsvc.h> | ||
106 | #include <linux/atmlec.h> | ||
107 | #include <linux/atmclip.h> | ||
108 | #include <linux/atmmpc.h> | ||
109 | #include <linux/atm_tcp.h> | ||
110 | #include <linux/sonet.h> | ||
111 | #include <linux/sockios.h> | ||
112 | #include <linux/atalk.h> | ||
113 | |||
100 | static int sock_no_open(struct inode *irrelevant, struct file *dontcare); | 114 | static int sock_no_open(struct inode *irrelevant, struct file *dontcare); |
101 | static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, | 115 | static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, |
102 | unsigned long nr_segs, loff_t pos); | 116 | unsigned long nr_segs, loff_t pos); |
@@ -919,6 +933,24 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *)) | |||
919 | 933 | ||
920 | EXPORT_SYMBOL(dlci_ioctl_set); | 934 | EXPORT_SYMBOL(dlci_ioctl_set); |
921 | 935 | ||
936 | static long sock_do_ioctl(struct net *net, struct socket *sock, | ||
937 | unsigned int cmd, unsigned long arg) | ||
938 | { | ||
939 | int err; | ||
940 | void __user *argp = (void __user *)arg; | ||
941 | |||
942 | err = sock->ops->ioctl(sock, cmd, arg); | ||
943 | |||
944 | /* | ||
945 | * If this ioctl is unknown try to hand it down | ||
946 | * to the NIC driver. | ||
947 | */ | ||
948 | if (err == -ENOIOCTLCMD) | ||
949 | err = dev_ioctl(net, cmd, argp); | ||
950 | |||
951 | return err; | ||
952 | } | ||
953 | |||
922 | /* | 954 | /* |
923 | * With an ioctl, arg may well be a user mode pointer, but we don't know | 955 | * With an ioctl, arg may well be a user mode pointer, but we don't know |
924 | * what to do with it - that's up to the protocol still. | 956 | * what to do with it - that's up to the protocol still. |
@@ -992,14 +1024,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
992 | mutex_unlock(&dlci_ioctl_mutex); | 1024 | mutex_unlock(&dlci_ioctl_mutex); |
993 | break; | 1025 | break; |
994 | default: | 1026 | default: |
995 | err = sock->ops->ioctl(sock, cmd, arg); | 1027 | err = sock_do_ioctl(net, sock, cmd, arg); |
996 | |||
997 | /* | ||
998 | * If this ioctl is unknown try to hand it down | ||
999 | * to the NIC driver. | ||
1000 | */ | ||
1001 | if (err == -ENOIOCTLCMD) | ||
1002 | err = dev_ioctl(net, cmd, argp); | ||
1003 | break; | 1028 | break; |
1004 | } | 1029 | } |
1005 | return err; | 1030 | return err; |
@@ -1252,7 +1277,7 @@ static int __sock_create(struct net *net, int family, int type, int protocol, | |||
1252 | /* Now protected by module ref count */ | 1277 | /* Now protected by module ref count */ |
1253 | rcu_read_unlock(); | 1278 | rcu_read_unlock(); |
1254 | 1279 | ||
1255 | err = pf->create(net, sock, protocol); | 1280 | err = pf->create(net, sock, protocol, kern); |
1256 | if (err < 0) | 1281 | if (err < 0) |
1257 | goto out_module_put; | 1282 | goto out_module_put; |
1258 | 1283 | ||
@@ -2459,6 +2484,735 @@ void socket_seq_show(struct seq_file *seq) | |||
2459 | #endif /* CONFIG_PROC_FS */ | 2484 | #endif /* CONFIG_PROC_FS */ |
2460 | 2485 | ||
2461 | #ifdef CONFIG_COMPAT | 2486 | #ifdef CONFIG_COMPAT |
2487 | static int do_siocgstamp(struct net *net, struct socket *sock, | ||
2488 | unsigned int cmd, struct compat_timeval __user *up) | ||
2489 | { | ||
2490 | mm_segment_t old_fs = get_fs(); | ||
2491 | struct timeval ktv; | ||
2492 | int err; | ||
2493 | |||
2494 | set_fs(KERNEL_DS); | ||
2495 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); | ||
2496 | set_fs(old_fs); | ||
2497 | if (!err) { | ||
2498 | err = put_user(ktv.tv_sec, &up->tv_sec); | ||
2499 | err |= __put_user(ktv.tv_usec, &up->tv_usec); | ||
2500 | } | ||
2501 | return err; | ||
2502 | } | ||
2503 | |||
2504 | static int do_siocgstampns(struct net *net, struct socket *sock, | ||
2505 | unsigned int cmd, struct compat_timespec __user *up) | ||
2506 | { | ||
2507 | mm_segment_t old_fs = get_fs(); | ||
2508 | struct timespec kts; | ||
2509 | int err; | ||
2510 | |||
2511 | set_fs(KERNEL_DS); | ||
2512 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); | ||
2513 | set_fs(old_fs); | ||
2514 | if (!err) { | ||
2515 | err = put_user(kts.tv_sec, &up->tv_sec); | ||
2516 | err |= __put_user(kts.tv_nsec, &up->tv_nsec); | ||
2517 | } | ||
2518 | return err; | ||
2519 | } | ||
2520 | |||
2521 | static int dev_ifname32(struct net *net, struct compat_ifreq __user *uifr32) | ||
2522 | { | ||
2523 | struct ifreq __user *uifr; | ||
2524 | int err; | ||
2525 | |||
2526 | uifr = compat_alloc_user_space(sizeof(struct ifreq)); | ||
2527 | if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) | ||
2528 | return -EFAULT; | ||
2529 | |||
2530 | err = dev_ioctl(net, SIOCGIFNAME, uifr); | ||
2531 | if (err) | ||
2532 | return err; | ||
2533 | |||
2534 | if (copy_in_user(uifr32, uifr, sizeof(struct compat_ifreq))) | ||
2535 | return -EFAULT; | ||
2536 | |||
2537 | return 0; | ||
2538 | } | ||
2539 | |||
2540 | static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | ||
2541 | { | ||
2542 | struct compat_ifconf ifc32; | ||
2543 | struct ifconf ifc; | ||
2544 | struct ifconf __user *uifc; | ||
2545 | struct compat_ifreq __user *ifr32; | ||
2546 | struct ifreq __user *ifr; | ||
2547 | unsigned int i, j; | ||
2548 | int err; | ||
2549 | |||
2550 | if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) | ||
2551 | return -EFAULT; | ||
2552 | |||
2553 | if (ifc32.ifcbuf == 0) { | ||
2554 | ifc32.ifc_len = 0; | ||
2555 | ifc.ifc_len = 0; | ||
2556 | ifc.ifc_req = NULL; | ||
2557 | uifc = compat_alloc_user_space(sizeof(struct ifconf)); | ||
2558 | } else { | ||
2559 | size_t len =((ifc32.ifc_len / sizeof (struct compat_ifreq)) + 1) * | ||
2560 | sizeof (struct ifreq); | ||
2561 | uifc = compat_alloc_user_space(sizeof(struct ifconf) + len); | ||
2562 | ifc.ifc_len = len; | ||
2563 | ifr = ifc.ifc_req = (void __user *)(uifc + 1); | ||
2564 | ifr32 = compat_ptr(ifc32.ifcbuf); | ||
2565 | for (i = 0; i < ifc32.ifc_len; i += sizeof (struct compat_ifreq)) { | ||
2566 | if (copy_in_user(ifr, ifr32, sizeof(struct compat_ifreq))) | ||
2567 | return -EFAULT; | ||
2568 | ifr++; | ||
2569 | ifr32++; | ||
2570 | } | ||
2571 | } | ||
2572 | if (copy_to_user(uifc, &ifc, sizeof(struct ifconf))) | ||
2573 | return -EFAULT; | ||
2574 | |||
2575 | err = dev_ioctl(net, SIOCGIFCONF, uifc); | ||
2576 | if (err) | ||
2577 | return err; | ||
2578 | |||
2579 | if (copy_from_user(&ifc, uifc, sizeof(struct ifconf))) | ||
2580 | return -EFAULT; | ||
2581 | |||
2582 | ifr = ifc.ifc_req; | ||
2583 | ifr32 = compat_ptr(ifc32.ifcbuf); | ||
2584 | for (i = 0, j = 0; | ||
2585 | i + sizeof (struct compat_ifreq) <= ifc32.ifc_len && j < ifc.ifc_len; | ||
2586 | i += sizeof (struct compat_ifreq), j += sizeof (struct ifreq)) { | ||
2587 | if (copy_in_user(ifr32, ifr, sizeof (struct compat_ifreq))) | ||
2588 | return -EFAULT; | ||
2589 | ifr32++; | ||
2590 | ifr++; | ||
2591 | } | ||
2592 | |||
2593 | if (ifc32.ifcbuf == 0) { | ||
2594 | /* Translate from 64-bit structure multiple to | ||
2595 | * a 32-bit one. | ||
2596 | */ | ||
2597 | i = ifc.ifc_len; | ||
2598 | i = ((i / sizeof(struct ifreq)) * sizeof(struct compat_ifreq)); | ||
2599 | ifc32.ifc_len = i; | ||
2600 | } else { | ||
2601 | ifc32.ifc_len = i; | ||
2602 | } | ||
2603 | if (copy_to_user(uifc32, &ifc32, sizeof(struct compat_ifconf))) | ||
2604 | return -EFAULT; | ||
2605 | |||
2606 | return 0; | ||
2607 | } | ||
2608 | |||
2609 | static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | ||
2610 | { | ||
2611 | struct ifreq __user *ifr; | ||
2612 | u32 data; | ||
2613 | void __user *datap; | ||
2614 | |||
2615 | ifr = compat_alloc_user_space(sizeof(*ifr)); | ||
2616 | |||
2617 | if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||
2618 | return -EFAULT; | ||
2619 | |||
2620 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | ||
2621 | return -EFAULT; | ||
2622 | |||
2623 | datap = compat_ptr(data); | ||
2624 | if (put_user(datap, &ifr->ifr_ifru.ifru_data)) | ||
2625 | return -EFAULT; | ||
2626 | |||
2627 | return dev_ioctl(net, SIOCETHTOOL, ifr); | ||
2628 | } | ||
2629 | |||
2630 | static int compat_siocwandev(struct net *net, struct compat_ifreq __user *uifr32) | ||
2631 | { | ||
2632 | void __user *uptr; | ||
2633 | compat_uptr_t uptr32; | ||
2634 | struct ifreq __user *uifr; | ||
2635 | |||
2636 | uifr = compat_alloc_user_space(sizeof (*uifr)); | ||
2637 | if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq))) | ||
2638 | return -EFAULT; | ||
2639 | |||
2640 | if (get_user(uptr32, &uifr32->ifr_settings.ifs_ifsu)) | ||
2641 | return -EFAULT; | ||
2642 | |||
2643 | uptr = compat_ptr(uptr32); | ||
2644 | |||
2645 | if (put_user(uptr, &uifr->ifr_settings.ifs_ifsu.raw_hdlc)) | ||
2646 | return -EFAULT; | ||
2647 | |||
2648 | return dev_ioctl(net, SIOCWANDEV, uifr); | ||
2649 | } | ||
2650 | |||
2651 | static int bond_ioctl(struct net *net, unsigned int cmd, | ||
2652 | struct compat_ifreq __user *ifr32) | ||
2653 | { | ||
2654 | struct ifreq kifr; | ||
2655 | struct ifreq __user *uifr; | ||
2656 | mm_segment_t old_fs; | ||
2657 | int err; | ||
2658 | u32 data; | ||
2659 | void __user *datap; | ||
2660 | |||
2661 | switch (cmd) { | ||
2662 | case SIOCBONDENSLAVE: | ||
2663 | case SIOCBONDRELEASE: | ||
2664 | case SIOCBONDSETHWADDR: | ||
2665 | case SIOCBONDCHANGEACTIVE: | ||
2666 | if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq))) | ||
2667 | return -EFAULT; | ||
2668 | |||
2669 | old_fs = get_fs(); | ||
2670 | set_fs (KERNEL_DS); | ||
2671 | err = dev_ioctl(net, cmd, &kifr); | ||
2672 | set_fs (old_fs); | ||
2673 | |||
2674 | return err; | ||
2675 | case SIOCBONDSLAVEINFOQUERY: | ||
2676 | case SIOCBONDINFOQUERY: | ||
2677 | uifr = compat_alloc_user_space(sizeof(*uifr)); | ||
2678 | if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ)) | ||
2679 | return -EFAULT; | ||
2680 | |||
2681 | if (get_user(data, &ifr32->ifr_ifru.ifru_data)) | ||
2682 | return -EFAULT; | ||
2683 | |||
2684 | datap = compat_ptr(data); | ||
2685 | if (put_user(datap, &uifr->ifr_ifru.ifru_data)) | ||
2686 | return -EFAULT; | ||
2687 | |||
2688 | return dev_ioctl(net, cmd, uifr); | ||
2689 | default: | ||
2690 | return -EINVAL; | ||
2691 | }; | ||
2692 | } | ||
2693 | |||
2694 | static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, | ||
2695 | struct compat_ifreq __user *u_ifreq32) | ||
2696 | { | ||
2697 | struct ifreq __user *u_ifreq64; | ||
2698 | char tmp_buf[IFNAMSIZ]; | ||
2699 | void __user *data64; | ||
2700 | u32 data32; | ||
2701 | |||
2702 | if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), | ||
2703 | IFNAMSIZ)) | ||
2704 | return -EFAULT; | ||
2705 | if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) | ||
2706 | return -EFAULT; | ||
2707 | data64 = compat_ptr(data32); | ||
2708 | |||
2709 | u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); | ||
2710 | |||
2711 | /* Don't check these user accesses, just let that get trapped | ||
2712 | * in the ioctl handler instead. | ||
2713 | */ | ||
2714 | if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], | ||
2715 | IFNAMSIZ)) | ||
2716 | return -EFAULT; | ||
2717 | if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) | ||
2718 | return -EFAULT; | ||
2719 | |||
2720 | return dev_ioctl(net, cmd, u_ifreq64); | ||
2721 | } | ||
2722 | |||
2723 | static int dev_ifsioc(struct net *net, struct socket *sock, | ||
2724 | unsigned int cmd, struct compat_ifreq __user *uifr32) | ||
2725 | { | ||
2726 | struct ifreq ifr; | ||
2727 | struct compat_ifmap __user *uifmap32; | ||
2728 | mm_segment_t old_fs; | ||
2729 | int err; | ||
2730 | |||
2731 | uifmap32 = &uifr32->ifr_ifru.ifru_map; | ||
2732 | switch (cmd) { | ||
2733 | case SIOCSIFMAP: | ||
2734 | err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name)); | ||
2735 | err |= __get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); | ||
2736 | err |= __get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); | ||
2737 | err |= __get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); | ||
2738 | err |= __get_user(ifr.ifr_map.irq, &uifmap32->irq); | ||
2739 | err |= __get_user(ifr.ifr_map.dma, &uifmap32->dma); | ||
2740 | err |= __get_user(ifr.ifr_map.port, &uifmap32->port); | ||
2741 | if (err) | ||
2742 | return -EFAULT; | ||
2743 | break; | ||
2744 | case SIOCSHWTSTAMP: | ||
2745 | if (copy_from_user(&ifr, uifr32, sizeof(*uifr32))) | ||
2746 | return -EFAULT; | ||
2747 | ifr.ifr_data = compat_ptr(uifr32->ifr_ifru.ifru_data); | ||
2748 | break; | ||
2749 | default: | ||
2750 | if (copy_from_user(&ifr, uifr32, sizeof(*uifr32))) | ||
2751 | return -EFAULT; | ||
2752 | break; | ||
2753 | } | ||
2754 | old_fs = get_fs(); | ||
2755 | set_fs (KERNEL_DS); | ||
2756 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ifr); | ||
2757 | set_fs (old_fs); | ||
2758 | if (!err) { | ||
2759 | switch (cmd) { | ||
2760 | case SIOCGIFFLAGS: | ||
2761 | case SIOCGIFMETRIC: | ||
2762 | case SIOCGIFMTU: | ||
2763 | case SIOCGIFMEM: | ||
2764 | case SIOCGIFHWADDR: | ||
2765 | case SIOCGIFINDEX: | ||
2766 | case SIOCGIFADDR: | ||
2767 | case SIOCGIFBRDADDR: | ||
2768 | case SIOCGIFDSTADDR: | ||
2769 | case SIOCGIFNETMASK: | ||
2770 | case SIOCGIFPFLAGS: | ||
2771 | case SIOCGIFTXQLEN: | ||
2772 | case SIOCGMIIPHY: | ||
2773 | case SIOCGMIIREG: | ||
2774 | if (copy_to_user(uifr32, &ifr, sizeof(*uifr32))) | ||
2775 | return -EFAULT; | ||
2776 | break; | ||
2777 | case SIOCGIFMAP: | ||
2778 | err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name)); | ||
2779 | err |= __put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start); | ||
2780 | err |= __put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end); | ||
2781 | err |= __put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr); | ||
2782 | err |= __put_user(ifr.ifr_map.irq, &uifmap32->irq); | ||
2783 | err |= __put_user(ifr.ifr_map.dma, &uifmap32->dma); | ||
2784 | err |= __put_user(ifr.ifr_map.port, &uifmap32->port); | ||
2785 | if (err) | ||
2786 | err = -EFAULT; | ||
2787 | break; | ||
2788 | } | ||
2789 | } | ||
2790 | return err; | ||
2791 | } | ||
2792 | |||
2793 | struct rtentry32 { | ||
2794 | u32 rt_pad1; | ||
2795 | struct sockaddr rt_dst; /* target address */ | ||
2796 | struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ | ||
2797 | struct sockaddr rt_genmask; /* target network mask (IP) */ | ||
2798 | unsigned short rt_flags; | ||
2799 | short rt_pad2; | ||
2800 | u32 rt_pad3; | ||
2801 | unsigned char rt_tos; | ||
2802 | unsigned char rt_class; | ||
2803 | short rt_pad4; | ||
2804 | short rt_metric; /* +1 for binary compatibility! */ | ||
2805 | /* char * */ u32 rt_dev; /* forcing the device at add */ | ||
2806 | u32 rt_mtu; /* per route MTU/Window */ | ||
2807 | u32 rt_window; /* Window clamping */ | ||
2808 | unsigned short rt_irtt; /* Initial RTT */ | ||
2809 | }; | ||
2810 | |||
2811 | struct in6_rtmsg32 { | ||
2812 | struct in6_addr rtmsg_dst; | ||
2813 | struct in6_addr rtmsg_src; | ||
2814 | struct in6_addr rtmsg_gateway; | ||
2815 | u32 rtmsg_type; | ||
2816 | u16 rtmsg_dst_len; | ||
2817 | u16 rtmsg_src_len; | ||
2818 | u32 rtmsg_metric; | ||
2819 | u32 rtmsg_info; | ||
2820 | u32 rtmsg_flags; | ||
2821 | s32 rtmsg_ifindex; | ||
2822 | }; | ||
2823 | |||
2824 | static int routing_ioctl(struct net *net, struct socket *sock, | ||
2825 | unsigned int cmd, void __user *argp) | ||
2826 | { | ||
2827 | int ret; | ||
2828 | void *r = NULL; | ||
2829 | struct in6_rtmsg r6; | ||
2830 | struct rtentry r4; | ||
2831 | char devname[16]; | ||
2832 | u32 rtdev; | ||
2833 | mm_segment_t old_fs = get_fs(); | ||
2834 | |||
2835 | if (sock && sock->sk && sock->sk->sk_family == AF_INET6) { /* ipv6 */ | ||
2836 | struct in6_rtmsg32 __user *ur6 = argp; | ||
2837 | ret = copy_from_user (&r6.rtmsg_dst, &(ur6->rtmsg_dst), | ||
2838 | 3 * sizeof(struct in6_addr)); | ||
2839 | ret |= __get_user (r6.rtmsg_type, &(ur6->rtmsg_type)); | ||
2840 | ret |= __get_user (r6.rtmsg_dst_len, &(ur6->rtmsg_dst_len)); | ||
2841 | ret |= __get_user (r6.rtmsg_src_len, &(ur6->rtmsg_src_len)); | ||
2842 | ret |= __get_user (r6.rtmsg_metric, &(ur6->rtmsg_metric)); | ||
2843 | ret |= __get_user (r6.rtmsg_info, &(ur6->rtmsg_info)); | ||
2844 | ret |= __get_user (r6.rtmsg_flags, &(ur6->rtmsg_flags)); | ||
2845 | ret |= __get_user (r6.rtmsg_ifindex, &(ur6->rtmsg_ifindex)); | ||
2846 | |||
2847 | r = (void *) &r6; | ||
2848 | } else { /* ipv4 */ | ||
2849 | struct rtentry32 __user *ur4 = argp; | ||
2850 | ret = copy_from_user (&r4.rt_dst, &(ur4->rt_dst), | ||
2851 | 3 * sizeof(struct sockaddr)); | ||
2852 | ret |= __get_user (r4.rt_flags, &(ur4->rt_flags)); | ||
2853 | ret |= __get_user (r4.rt_metric, &(ur4->rt_metric)); | ||
2854 | ret |= __get_user (r4.rt_mtu, &(ur4->rt_mtu)); | ||
2855 | ret |= __get_user (r4.rt_window, &(ur4->rt_window)); | ||
2856 | ret |= __get_user (r4.rt_irtt, &(ur4->rt_irtt)); | ||
2857 | ret |= __get_user (rtdev, &(ur4->rt_dev)); | ||
2858 | if (rtdev) { | ||
2859 | ret |= copy_from_user (devname, compat_ptr(rtdev), 15); | ||
2860 | r4.rt_dev = devname; devname[15] = 0; | ||
2861 | } else | ||
2862 | r4.rt_dev = NULL; | ||
2863 | |||
2864 | r = (void *) &r4; | ||
2865 | } | ||
2866 | |||
2867 | if (ret) { | ||
2868 | ret = -EFAULT; | ||
2869 | goto out; | ||
2870 | } | ||
2871 | |||
2872 | set_fs (KERNEL_DS); | ||
2873 | ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r); | ||
2874 | set_fs (old_fs); | ||
2875 | |||
2876 | out: | ||
2877 | return ret; | ||
2878 | } | ||
2879 | |||
2880 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE | ||
2881 | * for some operations; this forces use of the newer bridge-utils that | ||
2882 | * use compatiable ioctls | ||
2883 | */ | ||
2884 | static int old_bridge_ioctl(compat_ulong_t __user *argp) | ||
2885 | { | ||
2886 | compat_ulong_t tmp; | ||
2887 | |||
2888 | if (get_user(tmp, argp)) | ||
2889 | return -EFAULT; | ||
2890 | if (tmp == BRCTL_GET_VERSION) | ||
2891 | return BRCTL_VERSION + 1; | ||
2892 | return -EINVAL; | ||
2893 | } | ||
2894 | |||
2895 | struct atmif_sioc32 { | ||
2896 | compat_int_t number; | ||
2897 | compat_int_t length; | ||
2898 | compat_caddr_t arg; | ||
2899 | }; | ||
2900 | |||
2901 | struct atm_iobuf32 { | ||
2902 | compat_int_t length; | ||
2903 | compat_caddr_t buffer; | ||
2904 | }; | ||
2905 | |||
2906 | #define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32) | ||
2907 | #define ATM_GETNAMES32 _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32) | ||
2908 | #define ATM_GETTYPE32 _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32) | ||
2909 | #define ATM_GETESI32 _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32) | ||
2910 | #define ATM_GETADDR32 _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32) | ||
2911 | #define ATM_RSTADDR32 _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32) | ||
2912 | #define ATM_ADDADDR32 _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32) | ||
2913 | #define ATM_DELADDR32 _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32) | ||
2914 | #define ATM_GETCIRANGE32 _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32) | ||
2915 | #define ATM_SETCIRANGE32 _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32) | ||
2916 | #define ATM_SETESI32 _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32) | ||
2917 | #define ATM_SETESIF32 _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32) | ||
2918 | #define ATM_GETSTAT32 _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32) | ||
2919 | #define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32) | ||
2920 | #define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32) | ||
2921 | #define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32) | ||
2922 | #define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32) | ||
2923 | |||
2924 | static struct { | ||
2925 | unsigned int cmd32; | ||
2926 | unsigned int cmd; | ||
2927 | } atm_ioctl_map[] = { | ||
2928 | { ATM_GETLINKRATE32, ATM_GETLINKRATE }, | ||
2929 | { ATM_GETNAMES32, ATM_GETNAMES }, | ||
2930 | { ATM_GETTYPE32, ATM_GETTYPE }, | ||
2931 | { ATM_GETESI32, ATM_GETESI }, | ||
2932 | { ATM_GETADDR32, ATM_GETADDR }, | ||
2933 | { ATM_RSTADDR32, ATM_RSTADDR }, | ||
2934 | { ATM_ADDADDR32, ATM_ADDADDR }, | ||
2935 | { ATM_DELADDR32, ATM_DELADDR }, | ||
2936 | { ATM_GETCIRANGE32, ATM_GETCIRANGE }, | ||
2937 | { ATM_SETCIRANGE32, ATM_SETCIRANGE }, | ||
2938 | { ATM_SETESI32, ATM_SETESI }, | ||
2939 | { ATM_SETESIF32, ATM_SETESIF }, | ||
2940 | { ATM_GETSTAT32, ATM_GETSTAT }, | ||
2941 | { ATM_GETSTATZ32, ATM_GETSTATZ }, | ||
2942 | { ATM_GETLOOP32, ATM_GETLOOP }, | ||
2943 | { ATM_SETLOOP32, ATM_SETLOOP }, | ||
2944 | { ATM_QUERYLOOP32, ATM_QUERYLOOP } | ||
2945 | }; | ||
2946 | |||
2947 | #define NR_ATM_IOCTL ARRAY_SIZE(atm_ioctl_map) | ||
2948 | |||
2949 | static int do_atm_iobuf(struct net *net, struct socket *sock, | ||
2950 | unsigned int cmd, unsigned long arg) | ||
2951 | { | ||
2952 | struct atm_iobuf __user *iobuf; | ||
2953 | struct atm_iobuf32 __user *iobuf32; | ||
2954 | u32 data; | ||
2955 | void __user *datap; | ||
2956 | int len, err; | ||
2957 | |||
2958 | iobuf = compat_alloc_user_space(sizeof(*iobuf)); | ||
2959 | iobuf32 = compat_ptr(arg); | ||
2960 | |||
2961 | if (get_user(len, &iobuf32->length) || | ||
2962 | get_user(data, &iobuf32->buffer)) | ||
2963 | return -EFAULT; | ||
2964 | datap = compat_ptr(data); | ||
2965 | if (put_user(len, &iobuf->length) || | ||
2966 | put_user(datap, &iobuf->buffer)) | ||
2967 | return -EFAULT; | ||
2968 | |||
2969 | err = sock_do_ioctl(net, sock, cmd, (unsigned long)iobuf); | ||
2970 | |||
2971 | if (!err) { | ||
2972 | if (copy_in_user(&iobuf32->length, &iobuf->length, | ||
2973 | sizeof(int))) | ||
2974 | err = -EFAULT; | ||
2975 | } | ||
2976 | |||
2977 | return err; | ||
2978 | } | ||
2979 | |||
2980 | static int do_atmif_sioc(struct net *net, struct socket *sock, | ||
2981 | unsigned int cmd, unsigned long arg) | ||
2982 | { | ||
2983 | struct atmif_sioc __user *sioc; | ||
2984 | struct atmif_sioc32 __user *sioc32; | ||
2985 | u32 data; | ||
2986 | void __user *datap; | ||
2987 | int err; | ||
2988 | |||
2989 | sioc = compat_alloc_user_space(sizeof(*sioc)); | ||
2990 | sioc32 = compat_ptr(arg); | ||
2991 | |||
2992 | if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) || | ||
2993 | get_user(data, &sioc32->arg)) | ||
2994 | return -EFAULT; | ||
2995 | datap = compat_ptr(data); | ||
2996 | if (put_user(datap, &sioc->arg)) | ||
2997 | return -EFAULT; | ||
2998 | |||
2999 | err = sock_do_ioctl(net, sock, cmd, (unsigned long) sioc); | ||
3000 | |||
3001 | if (!err) { | ||
3002 | if (copy_in_user(&sioc32->length, &sioc->length, | ||
3003 | sizeof(int))) | ||
3004 | err = -EFAULT; | ||
3005 | } | ||
3006 | return err; | ||
3007 | } | ||
3008 | |||
3009 | static int do_atm_ioctl(struct net *net, struct socket *sock, | ||
3010 | unsigned int cmd32, unsigned long arg) | ||
3011 | { | ||
3012 | int i; | ||
3013 | unsigned int cmd = 0; | ||
3014 | |||
3015 | switch (cmd32) { | ||
3016 | case SONET_GETSTAT: | ||
3017 | case SONET_GETSTATZ: | ||
3018 | case SONET_GETDIAG: | ||
3019 | case SONET_SETDIAG: | ||
3020 | case SONET_CLRDIAG: | ||
3021 | case SONET_SETFRAMING: | ||
3022 | case SONET_GETFRAMING: | ||
3023 | case SONET_GETFRSENSE: | ||
3024 | return do_atmif_sioc(net, sock, cmd32, arg); | ||
3025 | } | ||
3026 | |||
3027 | for (i = 0; i < NR_ATM_IOCTL; i++) { | ||
3028 | if (cmd32 == atm_ioctl_map[i].cmd32) { | ||
3029 | cmd = atm_ioctl_map[i].cmd; | ||
3030 | break; | ||
3031 | } | ||
3032 | } | ||
3033 | if (i == NR_ATM_IOCTL) | ||
3034 | return -EINVAL; | ||
3035 | |||
3036 | switch (cmd) { | ||
3037 | case ATM_GETNAMES: | ||
3038 | return do_atm_iobuf(net, sock, cmd, arg); | ||
3039 | |||
3040 | case ATM_GETLINKRATE: | ||
3041 | case ATM_GETTYPE: | ||
3042 | case ATM_GETESI: | ||
3043 | case ATM_GETADDR: | ||
3044 | case ATM_RSTADDR: | ||
3045 | case ATM_ADDADDR: | ||
3046 | case ATM_DELADDR: | ||
3047 | case ATM_GETCIRANGE: | ||
3048 | case ATM_SETCIRANGE: | ||
3049 | case ATM_SETESI: | ||
3050 | case ATM_SETESIF: | ||
3051 | case ATM_GETSTAT: | ||
3052 | case ATM_GETSTATZ: | ||
3053 | case ATM_GETLOOP: | ||
3054 | case ATM_SETLOOP: | ||
3055 | case ATM_QUERYLOOP: | ||
3056 | return do_atmif_sioc(net, sock, cmd, arg); | ||
3057 | } | ||
3058 | |||
3059 | return -EINVAL; | ||
3060 | } | ||
3061 | |||
3062 | static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | ||
3063 | unsigned int cmd, unsigned long arg) | ||
3064 | { | ||
3065 | void __user *argp = compat_ptr(arg); | ||
3066 | struct sock *sk = sock->sk; | ||
3067 | struct net *net = sock_net(sk); | ||
3068 | |||
3069 | if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) | ||
3070 | return siocdevprivate_ioctl(net, cmd, argp); | ||
3071 | |||
3072 | switch (cmd) { | ||
3073 | case SIOCSIFBR: | ||
3074 | case SIOCGIFBR: | ||
3075 | return old_bridge_ioctl(argp); | ||
3076 | case SIOCGIFNAME: | ||
3077 | return dev_ifname32(net, argp); | ||
3078 | case SIOCGIFCONF: | ||
3079 | return dev_ifconf(net, argp); | ||
3080 | case SIOCETHTOOL: | ||
3081 | return ethtool_ioctl(net, argp); | ||
3082 | case SIOCWANDEV: | ||
3083 | return compat_siocwandev(net, argp); | ||
3084 | case SIOCBONDENSLAVE: | ||
3085 | case SIOCBONDRELEASE: | ||
3086 | case SIOCBONDSETHWADDR: | ||
3087 | case SIOCBONDSLAVEINFOQUERY: | ||
3088 | case SIOCBONDINFOQUERY: | ||
3089 | case SIOCBONDCHANGEACTIVE: | ||
3090 | return bond_ioctl(net, cmd, argp); | ||
3091 | case SIOCADDRT: | ||
3092 | case SIOCDELRT: | ||
3093 | return routing_ioctl(net, sock, cmd, argp); | ||
3094 | case SIOCGSTAMP: | ||
3095 | return do_siocgstamp(net, sock, cmd, argp); | ||
3096 | case SIOCGSTAMPNS: | ||
3097 | return do_siocgstampns(net, sock, cmd, argp); | ||
3098 | |||
3099 | case FIOSETOWN: | ||
3100 | case SIOCSPGRP: | ||
3101 | case FIOGETOWN: | ||
3102 | case SIOCGPGRP: | ||
3103 | case SIOCBRADDBR: | ||
3104 | case SIOCBRDELBR: | ||
3105 | case SIOCGIFVLAN: | ||
3106 | case SIOCSIFVLAN: | ||
3107 | case SIOCADDDLCI: | ||
3108 | case SIOCDELDLCI: | ||
3109 | return sock_ioctl(file, cmd, arg); | ||
3110 | |||
3111 | case SIOCGIFFLAGS: | ||
3112 | case SIOCSIFFLAGS: | ||
3113 | case SIOCGIFMETRIC: | ||
3114 | case SIOCSIFMETRIC: | ||
3115 | case SIOCGIFMTU: | ||
3116 | case SIOCSIFMTU: | ||
3117 | case SIOCGIFMEM: | ||
3118 | case SIOCSIFMEM: | ||
3119 | case SIOCGIFHWADDR: | ||
3120 | case SIOCSIFHWADDR: | ||
3121 | case SIOCADDMULTI: | ||
3122 | case SIOCDELMULTI: | ||
3123 | case SIOCGIFINDEX: | ||
3124 | case SIOCGIFMAP: | ||
3125 | case SIOCSIFMAP: | ||
3126 | case SIOCGIFADDR: | ||
3127 | case SIOCSIFADDR: | ||
3128 | case SIOCSIFHWBROADCAST: | ||
3129 | case SIOCSHWTSTAMP: | ||
3130 | case SIOCDIFADDR: | ||
3131 | case SIOCGIFBRDADDR: | ||
3132 | case SIOCSIFBRDADDR: | ||
3133 | case SIOCGIFDSTADDR: | ||
3134 | case SIOCSIFDSTADDR: | ||
3135 | case SIOCGIFNETMASK: | ||
3136 | case SIOCSIFNETMASK: | ||
3137 | case SIOCSIFPFLAGS: | ||
3138 | case SIOCGIFPFLAGS: | ||
3139 | case SIOCGIFTXQLEN: | ||
3140 | case SIOCSIFTXQLEN: | ||
3141 | case SIOCBRADDIF: | ||
3142 | case SIOCBRDELIF: | ||
3143 | case SIOCSIFNAME: | ||
3144 | case SIOCGMIIPHY: | ||
3145 | case SIOCGMIIREG: | ||
3146 | case SIOCSMIIREG: | ||
3147 | return dev_ifsioc(net, sock, cmd, argp); | ||
3148 | |||
3149 | case ATM_GETLINKRATE32: | ||
3150 | case ATM_GETNAMES32: | ||
3151 | case ATM_GETTYPE32: | ||
3152 | case ATM_GETESI32: | ||
3153 | case ATM_GETADDR32: | ||
3154 | case ATM_RSTADDR32: | ||
3155 | case ATM_ADDADDR32: | ||
3156 | case ATM_DELADDR32: | ||
3157 | case ATM_GETCIRANGE32: | ||
3158 | case ATM_SETCIRANGE32: | ||
3159 | case ATM_SETESI32: | ||
3160 | case ATM_SETESIF32: | ||
3161 | case ATM_GETSTAT32: | ||
3162 | case ATM_GETSTATZ32: | ||
3163 | case ATM_GETLOOP32: | ||
3164 | case ATM_SETLOOP32: | ||
3165 | case ATM_QUERYLOOP32: | ||
3166 | case SONET_GETSTAT: | ||
3167 | case SONET_GETSTATZ: | ||
3168 | case SONET_GETDIAG: | ||
3169 | case SONET_SETDIAG: | ||
3170 | case SONET_CLRDIAG: | ||
3171 | case SONET_SETFRAMING: | ||
3172 | case SONET_GETFRAMING: | ||
3173 | case SONET_GETFRSENSE: | ||
3174 | return do_atm_ioctl(net, sock, cmd, arg); | ||
3175 | |||
3176 | case ATMSIGD_CTRL: | ||
3177 | case ATMARPD_CTRL: | ||
3178 | case ATMLEC_CTRL: | ||
3179 | case ATMLEC_MCAST: | ||
3180 | case ATMLEC_DATA: | ||
3181 | case ATM_SETSC: | ||
3182 | case SIOCSIFATMTCP: | ||
3183 | case SIOCMKCLIP: | ||
3184 | case ATMARP_MKIP: | ||
3185 | case ATMARP_SETENTRY: | ||
3186 | case ATMARP_ENCAP: | ||
3187 | case ATMTCP_CREATE: | ||
3188 | case ATMTCP_REMOVE: | ||
3189 | case ATMMPC_CTRL: | ||
3190 | case ATMMPC_DATA: | ||
3191 | |||
3192 | case SIOCSARP: | ||
3193 | case SIOCGARP: | ||
3194 | case SIOCDARP: | ||
3195 | case SIOCATMARK: | ||
3196 | return sock_do_ioctl(net, sock, cmd, arg); | ||
3197 | } | ||
3198 | |||
3199 | /* Prevent warning from compat_sys_ioctl, these always | ||
3200 | * result in -EINVAL in the native case anyway. */ | ||
3201 | switch (cmd) { | ||
3202 | case SIOCRTMSG: | ||
3203 | case SIOCGIFCOUNT: | ||
3204 | case SIOCSRARP: | ||
3205 | case SIOCGRARP: | ||
3206 | case SIOCDRARP: | ||
3207 | case SIOCSIFLINK: | ||
3208 | case SIOCGIFSLAVE: | ||
3209 | case SIOCSIFSLAVE: | ||
3210 | return -EINVAL; | ||
3211 | } | ||
3212 | |||
3213 | return -ENOIOCTLCMD; | ||
3214 | } | ||
3215 | |||
2462 | static long compat_sock_ioctl(struct file *file, unsigned cmd, | 3216 | static long compat_sock_ioctl(struct file *file, unsigned cmd, |
2463 | unsigned long arg) | 3217 | unsigned long arg) |
2464 | { | 3218 | { |
@@ -2477,6 +3231,9 @@ static long compat_sock_ioctl(struct file *file, unsigned cmd, | |||
2477 | (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) | 3231 | (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)) |
2478 | ret = compat_wext_handle_ioctl(net, cmd, arg); | 3232 | ret = compat_wext_handle_ioctl(net, cmd, arg); |
2479 | 3233 | ||
3234 | if (ret == -ENOIOCTLCMD) | ||
3235 | ret = compat_sock_ioctl_trans(file, sock, cmd, arg); | ||
3236 | |||
2480 | return ret; | 3237 | return ret; |
2481 | } | 3238 | } |
2482 | #endif | 3239 | #endif |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index c2a17876defd..870929e08e5d 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -111,7 +111,7 @@ static void svc_release_skb(struct svc_rqst *rqstp) | |||
111 | rqstp->rq_xprt_ctxt = NULL; | 111 | rqstp->rq_xprt_ctxt = NULL; |
112 | 112 | ||
113 | dprintk("svc: service %p, releasing skb %p\n", rqstp, skb); | 113 | dprintk("svc: service %p, releasing skb %p\n", rqstp, skb); |
114 | skb_free_datagram(svsk->sk_sk, skb); | 114 | skb_free_datagram_locked(svsk->sk_sk, skb); |
115 | } | 115 | } |
116 | } | 116 | } |
117 | 117 | ||
@@ -578,7 +578,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
578 | "svc: received unknown control message %d/%d; " | 578 | "svc: received unknown control message %d/%d; " |
579 | "dropping RPC reply datagram\n", | 579 | "dropping RPC reply datagram\n", |
580 | cmh->cmsg_level, cmh->cmsg_type); | 580 | cmh->cmsg_level, cmh->cmsg_type); |
581 | skb_free_datagram(svsk->sk_sk, skb); | 581 | skb_free_datagram_locked(svsk->sk_sk, skb); |
582 | return 0; | 582 | return 0; |
583 | } | 583 | } |
584 | 584 | ||
@@ -588,18 +588,18 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
588 | if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { | 588 | if (csum_partial_copy_to_xdr(&rqstp->rq_arg, skb)) { |
589 | local_bh_enable(); | 589 | local_bh_enable(); |
590 | /* checksum error */ | 590 | /* checksum error */ |
591 | skb_free_datagram(svsk->sk_sk, skb); | 591 | skb_free_datagram_locked(svsk->sk_sk, skb); |
592 | return 0; | 592 | return 0; |
593 | } | 593 | } |
594 | local_bh_enable(); | 594 | local_bh_enable(); |
595 | skb_free_datagram(svsk->sk_sk, skb); | 595 | skb_free_datagram_locked(svsk->sk_sk, skb); |
596 | } else { | 596 | } else { |
597 | /* we can use it in-place */ | 597 | /* we can use it in-place */ |
598 | rqstp->rq_arg.head[0].iov_base = skb->data + | 598 | rqstp->rq_arg.head[0].iov_base = skb->data + |
599 | sizeof(struct udphdr); | 599 | sizeof(struct udphdr); |
600 | rqstp->rq_arg.head[0].iov_len = len; | 600 | rqstp->rq_arg.head[0].iov_len = len; |
601 | if (skb_checksum_complete(skb)) { | 601 | if (skb_checksum_complete(skb)) { |
602 | skb_free_datagram(svsk->sk_sk, skb); | 602 | skb_free_datagram_locked(svsk->sk_sk, skb); |
603 | return 0; | 603 | return 0; |
604 | } | 604 | } |
605 | rqstp->rq_xprt_ctxt = skb; | 605 | rqstp->rq_xprt_ctxt = skb; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index e6d9abf7440e..d00c2119faf3 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -177,6 +177,7 @@ static void reject_rx_queue(struct sock *sk) | |||
177 | * @net: network namespace (must be default network) | 177 | * @net: network namespace (must be default network) |
178 | * @sock: pre-allocated socket structure | 178 | * @sock: pre-allocated socket structure |
179 | * @protocol: protocol indicator (must be 0) | 179 | * @protocol: protocol indicator (must be 0) |
180 | * @kern: caused by kernel or by userspace? | ||
180 | * | 181 | * |
181 | * This routine creates additional data structures used by the TIPC socket, | 182 | * This routine creates additional data structures used by the TIPC socket, |
182 | * initializes them, and links them together. | 183 | * initializes them, and links them together. |
@@ -184,7 +185,8 @@ static void reject_rx_queue(struct sock *sk) | |||
184 | * Returns 0 on success, errno otherwise | 185 | * Returns 0 on success, errno otherwise |
185 | */ | 186 | */ |
186 | 187 | ||
187 | static int tipc_create(struct net *net, struct socket *sock, int protocol) | 188 | static int tipc_create(struct net *net, struct socket *sock, int protocol, |
189 | int kern) | ||
188 | { | 190 | { |
189 | const struct proto_ops *ops; | 191 | const struct proto_ops *ops; |
190 | socket_state state; | 192 | socket_state state; |
@@ -1528,7 +1530,7 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
1528 | 1530 | ||
1529 | buf = skb_peek(&sk->sk_receive_queue); | 1531 | buf = skb_peek(&sk->sk_receive_queue); |
1530 | 1532 | ||
1531 | res = tipc_create(sock_net(sock->sk), new_sock, 0); | 1533 | res = tipc_create(sock_net(sock->sk), new_sock, 0, 0); |
1532 | if (!res) { | 1534 | if (!res) { |
1533 | struct sock *new_sk = new_sock->sk; | 1535 | struct sock *new_sk = new_sock->sk; |
1534 | struct tipc_sock *new_tsock = tipc_sk(new_sk); | 1536 | struct tipc_sock *new_tsock = tipc_sk(new_sk); |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 3291902f0b88..178d3af2a605 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -621,7 +621,8 @@ out: | |||
621 | return sk; | 621 | return sk; |
622 | } | 622 | } |
623 | 623 | ||
624 | static int unix_create(struct net *net, struct socket *sock, int protocol) | 624 | static int unix_create(struct net *net, struct socket *sock, int protocol, |
625 | int kern) | ||
625 | { | 626 | { |
626 | if (protocol && protocol != PF_UNIX) | 627 | if (protocol && protocol != PF_UNIX) |
627 | return -EPROTONOSUPPORT; | 628 | return -EPROTONOSUPPORT; |
diff --git a/net/wimax/op-msg.c b/net/wimax/op-msg.c index d631a17186bc..d3bfb6ef13ae 100644 --- a/net/wimax/op-msg.c +++ b/net/wimax/op-msg.c | |||
@@ -388,6 +388,8 @@ int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info) | |||
388 | } | 388 | } |
389 | mutex_lock(&wimax_dev->mutex); | 389 | mutex_lock(&wimax_dev->mutex); |
390 | result = wimax_dev_is_ready(wimax_dev); | 390 | result = wimax_dev_is_ready(wimax_dev); |
391 | if (result == -ENOMEDIUM) | ||
392 | result = 0; | ||
391 | if (result < 0) | 393 | if (result < 0) |
392 | goto error_not_ready; | 394 | goto error_not_ready; |
393 | result = -ENOSYS; | 395 | result = -ENOSYS; |
diff --git a/net/wimax/op-rfkill.c b/net/wimax/op-rfkill.c index 70ef4df863b9..94d339c345d2 100644 --- a/net/wimax/op-rfkill.c +++ b/net/wimax/op-rfkill.c | |||
@@ -305,8 +305,15 @@ int wimax_rfkill(struct wimax_dev *wimax_dev, enum wimax_rf_state state) | |||
305 | d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); | 305 | d_fnstart(3, dev, "(wimax_dev %p state %u)\n", wimax_dev, state); |
306 | mutex_lock(&wimax_dev->mutex); | 306 | mutex_lock(&wimax_dev->mutex); |
307 | result = wimax_dev_is_ready(wimax_dev); | 307 | result = wimax_dev_is_ready(wimax_dev); |
308 | if (result < 0) | 308 | if (result < 0) { |
309 | /* While initializing, < 1.4.3 wimax-tools versions use | ||
310 | * this call to check if the device is a valid WiMAX | ||
311 | * device; so we allow it to proceed always, | ||
312 | * considering the radios are all off. */ | ||
313 | if (result == -ENOMEDIUM && state == WIMAX_RF_QUERY) | ||
314 | result = WIMAX_RF_OFF << 1 | WIMAX_RF_OFF; | ||
309 | goto error_not_ready; | 315 | goto error_not_ready; |
316 | } | ||
310 | switch (state) { | 317 | switch (state) { |
311 | case WIMAX_RF_ON: | 318 | case WIMAX_RF_ON: |
312 | case WIMAX_RF_OFF: | 319 | case WIMAX_RF_OFF: |
@@ -355,6 +362,7 @@ int wimax_rfkill_add(struct wimax_dev *wimax_dev) | |||
355 | 362 | ||
356 | wimax_dev->rfkill = rfkill; | 363 | wimax_dev->rfkill = rfkill; |
357 | 364 | ||
365 | rfkill_init_sw_state(rfkill, 1); | ||
358 | result = rfkill_register(wimax_dev->rfkill); | 366 | result = rfkill_register(wimax_dev->rfkill); |
359 | if (result < 0) | 367 | if (result < 0) |
360 | goto error_rfkill_register; | 368 | goto error_rfkill_register; |
diff --git a/net/wimax/stack.c b/net/wimax/stack.c index 79fb7d7c640f..c8866412f830 100644 --- a/net/wimax/stack.c +++ b/net/wimax/stack.c | |||
@@ -60,6 +60,14 @@ | |||
60 | #define D_SUBMODULE stack | 60 | #define D_SUBMODULE stack |
61 | #include "debug-levels.h" | 61 | #include "debug-levels.h" |
62 | 62 | ||
63 | static char wimax_debug_params[128]; | ||
64 | module_param_string(debug, wimax_debug_params, sizeof(wimax_debug_params), | ||
65 | 0644); | ||
66 | MODULE_PARM_DESC(debug, | ||
67 | "String of space-separated NAME:VALUE pairs, where NAMEs " | ||
68 | "are the different debug submodules and VALUE are the " | ||
69 | "initial debug value to set."); | ||
70 | |||
63 | /* | 71 | /* |
64 | * Authoritative source for the RE_STATE_CHANGE attribute policy | 72 | * Authoritative source for the RE_STATE_CHANGE attribute policy |
65 | * | 73 | * |
@@ -562,6 +570,9 @@ int __init wimax_subsys_init(void) | |||
562 | int result, cnt; | 570 | int result, cnt; |
563 | 571 | ||
564 | d_fnstart(4, NULL, "()\n"); | 572 | d_fnstart(4, NULL, "()\n"); |
573 | d_parse_params(D_LEVEL, D_LEVEL_SIZE, wimax_debug_params, | ||
574 | "wimax.debug"); | ||
575 | |||
565 | snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name), | 576 | snprintf(wimax_gnl_family.name, sizeof(wimax_gnl_family.name), |
566 | "WiMAX"); | 577 | "WiMAX"); |
567 | result = genl_register_family(&wimax_gnl_family); | 578 | result = genl_register_family(&wimax_gnl_family); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 98a3b7efac4c..0115d07d2c1a 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -165,7 +165,7 @@ void cfg80211_conn_work(struct work_struct *work) | |||
165 | struct cfg80211_registered_device *rdev = | 165 | struct cfg80211_registered_device *rdev = |
166 | container_of(work, struct cfg80211_registered_device, conn_work); | 166 | container_of(work, struct cfg80211_registered_device, conn_work); |
167 | struct wireless_dev *wdev; | 167 | struct wireless_dev *wdev; |
168 | u8 bssid[ETH_ALEN]; | 168 | u8 bssid_buf[ETH_ALEN], *bssid = NULL; |
169 | 169 | ||
170 | rtnl_lock(); | 170 | rtnl_lock(); |
171 | cfg80211_lock_rdev(rdev); | 171 | cfg80211_lock_rdev(rdev); |
@@ -181,7 +181,10 @@ void cfg80211_conn_work(struct work_struct *work) | |||
181 | wdev_unlock(wdev); | 181 | wdev_unlock(wdev); |
182 | continue; | 182 | continue; |
183 | } | 183 | } |
184 | memcpy(bssid, wdev->conn->params.bssid, ETH_ALEN); | 184 | if (wdev->conn->params.bssid) { |
185 | memcpy(bssid_buf, wdev->conn->params.bssid, ETH_ALEN); | ||
186 | bssid = bssid_buf; | ||
187 | } | ||
185 | if (cfg80211_conn_do_work(wdev)) | 188 | if (cfg80211_conn_do_work(wdev)) |
186 | __cfg80211_connect_result( | 189 | __cfg80211_connect_result( |
187 | wdev->netdev, bssid, | 190 | wdev->netdev, bssid, |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e19d811788a5..39ce03e07d18 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
415 | struct sock *sk = sock->sk; | 415 | struct sock *sk = sock->sk; |
416 | int rc = -ENOPROTOOPT; | 416 | int rc = -ENOPROTOOPT; |
417 | 417 | ||
418 | lock_kernel(); | ||
418 | if (level != SOL_X25 || optname != X25_QBITINCL) | 419 | if (level != SOL_X25 || optname != X25_QBITINCL) |
419 | goto out; | 420 | goto out; |
420 | 421 | ||
@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname, | |||
429 | x25_sk(sk)->qbitincl = !!opt; | 430 | x25_sk(sk)->qbitincl = !!opt; |
430 | rc = 0; | 431 | rc = 0; |
431 | out: | 432 | out: |
433 | unlock_kernel(); | ||
432 | return rc; | 434 | return rc; |
433 | } | 435 | } |
434 | 436 | ||
@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
438 | struct sock *sk = sock->sk; | 440 | struct sock *sk = sock->sk; |
439 | int val, len, rc = -ENOPROTOOPT; | 441 | int val, len, rc = -ENOPROTOOPT; |
440 | 442 | ||
443 | lock_kernel(); | ||
441 | if (level != SOL_X25 || optname != X25_QBITINCL) | 444 | if (level != SOL_X25 || optname != X25_QBITINCL) |
442 | goto out; | 445 | goto out; |
443 | 446 | ||
@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname, | |||
458 | val = x25_sk(sk)->qbitincl; | 461 | val = x25_sk(sk)->qbitincl; |
459 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; | 462 | rc = copy_to_user(optval, &val, len) ? -EFAULT : 0; |
460 | out: | 463 | out: |
464 | unlock_kernel(); | ||
461 | return rc; | 465 | return rc; |
462 | } | 466 | } |
463 | 467 | ||
@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog) | |||
466 | struct sock *sk = sock->sk; | 470 | struct sock *sk = sock->sk; |
467 | int rc = -EOPNOTSUPP; | 471 | int rc = -EOPNOTSUPP; |
468 | 472 | ||
473 | lock_kernel(); | ||
469 | if (sk->sk_state != TCP_LISTEN) { | 474 | if (sk->sk_state != TCP_LISTEN) { |
470 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); | 475 | memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN); |
471 | sk->sk_max_ack_backlog = backlog; | 476 | sk->sk_max_ack_backlog = backlog; |
472 | sk->sk_state = TCP_LISTEN; | 477 | sk->sk_state = TCP_LISTEN; |
473 | rc = 0; | 478 | rc = 0; |
474 | } | 479 | } |
480 | unlock_kernel(); | ||
475 | 481 | ||
476 | return rc; | 482 | return rc; |
477 | } | 483 | } |
@@ -501,7 +507,8 @@ out: | |||
501 | return sk; | 507 | return sk; |
502 | } | 508 | } |
503 | 509 | ||
504 | static int x25_create(struct net *net, struct socket *sock, int protocol) | 510 | static int x25_create(struct net *net, struct socket *sock, int protocol, |
511 | int kern) | ||
505 | { | 512 | { |
506 | struct sock *sk; | 513 | struct sock *sk; |
507 | struct x25_sock *x25; | 514 | struct x25_sock *x25; |
@@ -597,6 +604,7 @@ static int x25_release(struct socket *sock) | |||
597 | struct sock *sk = sock->sk; | 604 | struct sock *sk = sock->sk; |
598 | struct x25_sock *x25; | 605 | struct x25_sock *x25; |
599 | 606 | ||
607 | lock_kernel(); | ||
600 | if (!sk) | 608 | if (!sk) |
601 | goto out; | 609 | goto out; |
602 | 610 | ||
@@ -627,6 +635,7 @@ static int x25_release(struct socket *sock) | |||
627 | 635 | ||
628 | sock_orphan(sk); | 636 | sock_orphan(sk); |
629 | out: | 637 | out: |
638 | unlock_kernel(); | ||
630 | return 0; | 639 | return 0; |
631 | } | 640 | } |
632 | 641 | ||
@@ -634,18 +643,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
634 | { | 643 | { |
635 | struct sock *sk = sock->sk; | 644 | struct sock *sk = sock->sk; |
636 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; | 645 | struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr; |
646 | int rc = 0; | ||
637 | 647 | ||
648 | lock_kernel(); | ||
638 | if (!sock_flag(sk, SOCK_ZAPPED) || | 649 | if (!sock_flag(sk, SOCK_ZAPPED) || |
639 | addr_len != sizeof(struct sockaddr_x25) || | 650 | addr_len != sizeof(struct sockaddr_x25) || |
640 | addr->sx25_family != AF_X25) | 651 | addr->sx25_family != AF_X25) { |
641 | return -EINVAL; | 652 | rc = -EINVAL; |
653 | goto out; | ||
654 | } | ||
642 | 655 | ||
643 | x25_sk(sk)->source_addr = addr->sx25_addr; | 656 | x25_sk(sk)->source_addr = addr->sx25_addr; |
644 | x25_insert_socket(sk); | 657 | x25_insert_socket(sk); |
645 | sock_reset_flag(sk, SOCK_ZAPPED); | 658 | sock_reset_flag(sk, SOCK_ZAPPED); |
646 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); | 659 | SOCK_DEBUG(sk, "x25_bind: socket is bound\n"); |
647 | 660 | out: | |
648 | return 0; | 661 | unlock_kernel(); |
662 | return rc; | ||
649 | } | 663 | } |
650 | 664 | ||
651 | static int x25_wait_for_connection_establishment(struct sock *sk) | 665 | static int x25_wait_for_connection_establishment(struct sock *sk) |
@@ -686,6 +700,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, | |||
686 | struct x25_route *rt; | 700 | struct x25_route *rt; |
687 | int rc = 0; | 701 | int rc = 0; |
688 | 702 | ||
703 | lock_kernel(); | ||
689 | lock_sock(sk); | 704 | lock_sock(sk); |
690 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { | 705 | if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { |
691 | sock->state = SS_CONNECTED; | 706 | sock->state = SS_CONNECTED; |
@@ -763,6 +778,7 @@ out_put_route: | |||
763 | x25_route_put(rt); | 778 | x25_route_put(rt); |
764 | out: | 779 | out: |
765 | release_sock(sk); | 780 | release_sock(sk); |
781 | unlock_kernel(); | ||
766 | return rc; | 782 | return rc; |
767 | } | 783 | } |
768 | 784 | ||
@@ -802,6 +818,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
802 | struct sk_buff *skb; | 818 | struct sk_buff *skb; |
803 | int rc = -EINVAL; | 819 | int rc = -EINVAL; |
804 | 820 | ||
821 | lock_kernel(); | ||
805 | if (!sk || sk->sk_state != TCP_LISTEN) | 822 | if (!sk || sk->sk_state != TCP_LISTEN) |
806 | goto out; | 823 | goto out; |
807 | 824 | ||
@@ -829,6 +846,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags) | |||
829 | out2: | 846 | out2: |
830 | release_sock(sk); | 847 | release_sock(sk); |
831 | out: | 848 | out: |
849 | unlock_kernel(); | ||
832 | return rc; | 850 | return rc; |
833 | } | 851 | } |
834 | 852 | ||
@@ -838,10 +856,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
838 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; | 856 | struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr; |
839 | struct sock *sk = sock->sk; | 857 | struct sock *sk = sock->sk; |
840 | struct x25_sock *x25 = x25_sk(sk); | 858 | struct x25_sock *x25 = x25_sk(sk); |
859 | int rc = 0; | ||
841 | 860 | ||
861 | lock_kernel(); | ||
842 | if (peer) { | 862 | if (peer) { |
843 | if (sk->sk_state != TCP_ESTABLISHED) | 863 | if (sk->sk_state != TCP_ESTABLISHED) { |
844 | return -ENOTCONN; | 864 | rc = -ENOTCONN; |
865 | goto out; | ||
866 | } | ||
845 | sx25->sx25_addr = x25->dest_addr; | 867 | sx25->sx25_addr = x25->dest_addr; |
846 | } else | 868 | } else |
847 | sx25->sx25_addr = x25->source_addr; | 869 | sx25->sx25_addr = x25->source_addr; |
@@ -849,7 +871,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, | |||
849 | sx25->sx25_family = AF_X25; | 871 | sx25->sx25_family = AF_X25; |
850 | *uaddr_len = sizeof(*sx25); | 872 | *uaddr_len = sizeof(*sx25); |
851 | 873 | ||
852 | return 0; | 874 | out: |
875 | unlock_kernel(); | ||
876 | return rc; | ||
877 | } | ||
878 | |||
879 | static unsigned int x25_datagram_poll(struct file *file, struct socket *sock, | ||
880 | poll_table *wait) | ||
881 | { | ||
882 | int rc; | ||
883 | |||
884 | lock_kernel(); | ||
885 | rc = datagram_poll(file, sock, wait); | ||
886 | unlock_kernel(); | ||
887 | |||
888 | return rc; | ||
853 | } | 889 | } |
854 | 890 | ||
855 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | 891 | int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, |
@@ -1002,6 +1038,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1002 | size_t size; | 1038 | size_t size; |
1003 | int qbit = 0, rc = -EINVAL; | 1039 | int qbit = 0, rc = -EINVAL; |
1004 | 1040 | ||
1041 | lock_kernel(); | ||
1005 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) | 1042 | if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) |
1006 | goto out; | 1043 | goto out; |
1007 | 1044 | ||
@@ -1166,6 +1203,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1166 | release_sock(sk); | 1203 | release_sock(sk); |
1167 | rc = len; | 1204 | rc = len; |
1168 | out: | 1205 | out: |
1206 | unlock_kernel(); | ||
1169 | return rc; | 1207 | return rc; |
1170 | out_kfree_skb: | 1208 | out_kfree_skb: |
1171 | kfree_skb(skb); | 1209 | kfree_skb(skb); |
@@ -1186,6 +1224,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1186 | unsigned char *asmptr; | 1224 | unsigned char *asmptr; |
1187 | int rc = -ENOTCONN; | 1225 | int rc = -ENOTCONN; |
1188 | 1226 | ||
1227 | lock_kernel(); | ||
1189 | /* | 1228 | /* |
1190 | * This works for seqpacket too. The receiver has ordered the queue for | 1229 | * This works for seqpacket too. The receiver has ordered the queue for |
1191 | * us! We do one quick check first though | 1230 | * us! We do one quick check first though |
@@ -1259,6 +1298,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1259 | out_free_dgram: | 1298 | out_free_dgram: |
1260 | skb_free_datagram(sk, skb); | 1299 | skb_free_datagram(sk, skb); |
1261 | out: | 1300 | out: |
1301 | unlock_kernel(); | ||
1262 | return rc; | 1302 | return rc; |
1263 | } | 1303 | } |
1264 | 1304 | ||
@@ -1270,6 +1310,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1270 | void __user *argp = (void __user *)arg; | 1310 | void __user *argp = (void __user *)arg; |
1271 | int rc; | 1311 | int rc; |
1272 | 1312 | ||
1313 | lock_kernel(); | ||
1273 | switch (cmd) { | 1314 | switch (cmd) { |
1274 | case TIOCOUTQ: { | 1315 | case TIOCOUTQ: { |
1275 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1316 | int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
@@ -1472,6 +1513,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1472 | rc = -ENOIOCTLCMD; | 1513 | rc = -ENOIOCTLCMD; |
1473 | break; | 1514 | break; |
1474 | } | 1515 | } |
1516 | unlock_kernel(); | ||
1475 | 1517 | ||
1476 | return rc; | 1518 | return rc; |
1477 | } | 1519 | } |
@@ -1542,15 +1584,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1542 | break; | 1584 | break; |
1543 | case SIOCGSTAMP: | 1585 | case SIOCGSTAMP: |
1544 | rc = -EINVAL; | 1586 | rc = -EINVAL; |
1587 | lock_kernel(); | ||
1545 | if (sk) | 1588 | if (sk) |
1546 | rc = compat_sock_get_timestamp(sk, | 1589 | rc = compat_sock_get_timestamp(sk, |
1547 | (struct timeval __user*)argp); | 1590 | (struct timeval __user*)argp); |
1591 | unlock_kernel(); | ||
1548 | break; | 1592 | break; |
1549 | case SIOCGSTAMPNS: | 1593 | case SIOCGSTAMPNS: |
1550 | rc = -EINVAL; | 1594 | rc = -EINVAL; |
1595 | lock_kernel(); | ||
1551 | if (sk) | 1596 | if (sk) |
1552 | rc = compat_sock_get_timestampns(sk, | 1597 | rc = compat_sock_get_timestampns(sk, |
1553 | (struct timespec __user*)argp); | 1598 | (struct timespec __user*)argp); |
1599 | unlock_kernel(); | ||
1554 | break; | 1600 | break; |
1555 | case SIOCGIFADDR: | 1601 | case SIOCGIFADDR: |
1556 | case SIOCSIFADDR: | 1602 | case SIOCSIFADDR: |
@@ -1569,16 +1615,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1569 | rc = -EPERM; | 1615 | rc = -EPERM; |
1570 | if (!capable(CAP_NET_ADMIN)) | 1616 | if (!capable(CAP_NET_ADMIN)) |
1571 | break; | 1617 | break; |
1618 | lock_kernel(); | ||
1572 | rc = x25_route_ioctl(cmd, argp); | 1619 | rc = x25_route_ioctl(cmd, argp); |
1620 | unlock_kernel(); | ||
1573 | break; | 1621 | break; |
1574 | case SIOCX25GSUBSCRIP: | 1622 | case SIOCX25GSUBSCRIP: |
1623 | lock_kernel(); | ||
1575 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1624 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1625 | unlock_kernel(); | ||
1576 | break; | 1626 | break; |
1577 | case SIOCX25SSUBSCRIP: | 1627 | case SIOCX25SSUBSCRIP: |
1578 | rc = -EPERM; | 1628 | rc = -EPERM; |
1579 | if (!capable(CAP_NET_ADMIN)) | 1629 | if (!capable(CAP_NET_ADMIN)) |
1580 | break; | 1630 | break; |
1631 | lock_kernel(); | ||
1581 | rc = compat_x25_subscr_ioctl(cmd, argp); | 1632 | rc = compat_x25_subscr_ioctl(cmd, argp); |
1633 | unlock_kernel(); | ||
1582 | break; | 1634 | break; |
1583 | case SIOCX25GFACILITIES: | 1635 | case SIOCX25GFACILITIES: |
1584 | case SIOCX25SFACILITIES: | 1636 | case SIOCX25SFACILITIES: |
@@ -1600,7 +1652,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | |||
1600 | } | 1652 | } |
1601 | #endif | 1653 | #endif |
1602 | 1654 | ||
1603 | static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | 1655 | static const struct proto_ops x25_proto_ops = { |
1604 | .family = AF_X25, | 1656 | .family = AF_X25, |
1605 | .owner = THIS_MODULE, | 1657 | .owner = THIS_MODULE, |
1606 | .release = x25_release, | 1658 | .release = x25_release, |
@@ -1609,7 +1661,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1609 | .socketpair = sock_no_socketpair, | 1661 | .socketpair = sock_no_socketpair, |
1610 | .accept = x25_accept, | 1662 | .accept = x25_accept, |
1611 | .getname = x25_getname, | 1663 | .getname = x25_getname, |
1612 | .poll = datagram_poll, | 1664 | .poll = x25_datagram_poll, |
1613 | .ioctl = x25_ioctl, | 1665 | .ioctl = x25_ioctl, |
1614 | #ifdef CONFIG_COMPAT | 1666 | #ifdef CONFIG_COMPAT |
1615 | .compat_ioctl = compat_x25_ioctl, | 1667 | .compat_ioctl = compat_x25_ioctl, |
@@ -1624,8 +1676,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { | |||
1624 | .sendpage = sock_no_sendpage, | 1676 | .sendpage = sock_no_sendpage, |
1625 | }; | 1677 | }; |
1626 | 1678 | ||
1627 | SOCKOPS_WRAP(x25_proto, AF_X25); | ||
1628 | |||
1629 | static struct packet_type x25_packet_type __read_mostly = { | 1679 | static struct packet_type x25_packet_type __read_mostly = { |
1630 | .type = cpu_to_be16(ETH_P_X25), | 1680 | .type = cpu_to_be16(ETH_P_X25), |
1631 | .func = x25_lapb_receive_frame, | 1681 | .func = x25_lapb_receive_frame, |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f2f7c638083e..e9ac0cec0877 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include <linux/cache.h> | 21 | #include <linux/cache.h> |
22 | #include <linux/audit.h> | 22 | #include <linux/audit.h> |
23 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
24 | #include <linux/ktime.h> | ||
25 | #include <linux/interrupt.h> | ||
26 | #include <linux/kernel.h> | ||
24 | 27 | ||
25 | #include "xfrm_hash.h" | 28 | #include "xfrm_hash.h" |
26 | 29 | ||
@@ -352,7 +355,7 @@ static void xfrm_put_mode(struct xfrm_mode *mode) | |||
352 | 355 | ||
353 | static void xfrm_state_gc_destroy(struct xfrm_state *x) | 356 | static void xfrm_state_gc_destroy(struct xfrm_state *x) |
354 | { | 357 | { |
355 | del_timer_sync(&x->timer); | 358 | tasklet_hrtimer_cancel(&x->mtimer); |
356 | del_timer_sync(&x->rtimer); | 359 | del_timer_sync(&x->rtimer); |
357 | kfree(x->aalg); | 360 | kfree(x->aalg); |
358 | kfree(x->ealg); | 361 | kfree(x->ealg); |
@@ -398,9 +401,10 @@ static inline unsigned long make_jiffies(long secs) | |||
398 | return secs*HZ; | 401 | return secs*HZ; |
399 | } | 402 | } |
400 | 403 | ||
401 | static void xfrm_timer_handler(unsigned long data) | 404 | static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) |
402 | { | 405 | { |
403 | struct xfrm_state *x = (struct xfrm_state*)data; | 406 | struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer); |
407 | struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer); | ||
404 | struct net *net = xs_net(x); | 408 | struct net *net = xs_net(x); |
405 | unsigned long now = get_seconds(); | 409 | unsigned long now = get_seconds(); |
406 | long next = LONG_MAX; | 410 | long next = LONG_MAX; |
@@ -451,8 +455,9 @@ static void xfrm_timer_handler(unsigned long data) | |||
451 | if (warn) | 455 | if (warn) |
452 | km_state_expired(x, 0, 0); | 456 | km_state_expired(x, 0, 0); |
453 | resched: | 457 | resched: |
454 | if (next != LONG_MAX) | 458 | if (next != LONG_MAX){ |
455 | mod_timer(&x->timer, jiffies + make_jiffies(next)); | 459 | tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL); |
460 | } | ||
456 | 461 | ||
457 | goto out; | 462 | goto out; |
458 | 463 | ||
@@ -474,6 +479,7 @@ expired: | |||
474 | 479 | ||
475 | out: | 480 | out: |
476 | spin_unlock(&x->lock); | 481 | spin_unlock(&x->lock); |
482 | return HRTIMER_NORESTART; | ||
477 | } | 483 | } |
478 | 484 | ||
479 | static void xfrm_replay_timer_handler(unsigned long data); | 485 | static void xfrm_replay_timer_handler(unsigned long data); |
@@ -492,7 +498,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) | |||
492 | INIT_HLIST_NODE(&x->bydst); | 498 | INIT_HLIST_NODE(&x->bydst); |
493 | INIT_HLIST_NODE(&x->bysrc); | 499 | INIT_HLIST_NODE(&x->bysrc); |
494 | INIT_HLIST_NODE(&x->byspi); | 500 | INIT_HLIST_NODE(&x->byspi); |
495 | setup_timer(&x->timer, xfrm_timer_handler, (unsigned long)x); | 501 | tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler, CLOCK_REALTIME, HRTIMER_MODE_ABS); |
496 | setup_timer(&x->rtimer, xfrm_replay_timer_handler, | 502 | setup_timer(&x->rtimer, xfrm_replay_timer_handler, |
497 | (unsigned long)x); | 503 | (unsigned long)x); |
498 | x->curlft.add_time = get_seconds(); | 504 | x->curlft.add_time = get_seconds(); |
@@ -843,8 +849,7 @@ found: | |||
843 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); | 849 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
844 | } | 850 | } |
845 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; | 851 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
846 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; | 852 | tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); |
847 | add_timer(&x->timer); | ||
848 | net->xfrm.state_num++; | 853 | net->xfrm.state_num++; |
849 | xfrm_hash_grow_check(net, x->bydst.next != NULL); | 854 | xfrm_hash_grow_check(net, x->bydst.next != NULL); |
850 | } else { | 855 | } else { |
@@ -921,7 +926,7 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
921 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); | 926 | hlist_add_head(&x->byspi, net->xfrm.state_byspi+h); |
922 | } | 927 | } |
923 | 928 | ||
924 | mod_timer(&x->timer, jiffies + HZ); | 929 | tasklet_hrtimer_start(&x->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL); |
925 | if (x->replay_maxage) | 930 | if (x->replay_maxage) |
926 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); | 931 | mod_timer(&x->rtimer, jiffies + x->replay_maxage); |
927 | 932 | ||
@@ -1019,8 +1024,7 @@ static struct xfrm_state *__find_acq_core(struct net *net, unsigned short family | |||
1019 | x->props.reqid = reqid; | 1024 | x->props.reqid = reqid; |
1020 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; | 1025 | x->lft.hard_add_expires_seconds = net->xfrm.sysctl_acq_expires; |
1021 | xfrm_state_hold(x); | 1026 | xfrm_state_hold(x); |
1022 | x->timer.expires = jiffies + net->xfrm.sysctl_acq_expires*HZ; | 1027 | tasklet_hrtimer_start(&x->mtimer, ktime_set(net->xfrm.sysctl_acq_expires, 0), HRTIMER_MODE_REL); |
1023 | add_timer(&x->timer); | ||
1024 | list_add(&x->km.all, &net->xfrm.state_all); | 1028 | list_add(&x->km.all, &net->xfrm.state_all); |
1025 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); | 1029 | hlist_add_head(&x->bydst, net->xfrm.state_bydst+h); |
1026 | h = xfrm_src_hash(net, daddr, saddr, family); | 1030 | h = xfrm_src_hash(net, daddr, saddr, family); |
@@ -1300,7 +1304,7 @@ out: | |||
1300 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); | 1304 | memcpy(&x1->lft, &x->lft, sizeof(x1->lft)); |
1301 | x1->km.dying = 0; | 1305 | x1->km.dying = 0; |
1302 | 1306 | ||
1303 | mod_timer(&x1->timer, jiffies + HZ); | 1307 | tasklet_hrtimer_start(&x1->mtimer, ktime_set(1, 0), HRTIMER_MODE_REL); |
1304 | if (x1->curlft.use_time) | 1308 | if (x1->curlft.use_time) |
1305 | xfrm_state_check_expire(x1); | 1309 | xfrm_state_check_expire(x1); |
1306 | 1310 | ||
@@ -1325,7 +1329,7 @@ int xfrm_state_check_expire(struct xfrm_state *x) | |||
1325 | if (x->curlft.bytes >= x->lft.hard_byte_limit || | 1329 | if (x->curlft.bytes >= x->lft.hard_byte_limit || |
1326 | x->curlft.packets >= x->lft.hard_packet_limit) { | 1330 | x->curlft.packets >= x->lft.hard_packet_limit) { |
1327 | x->km.state = XFRM_STATE_EXPIRED; | 1331 | x->km.state = XFRM_STATE_EXPIRED; |
1328 | mod_timer(&x->timer, jiffies); | 1332 | tasklet_hrtimer_start(&x->mtimer, ktime_set(0,0), HRTIMER_MODE_REL); |
1329 | return -EINVAL; | 1333 | return -EINVAL; |
1330 | } | 1334 | } |
1331 | 1335 | ||