diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/bridge/br_if.c | 6 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 2 | ||||
| -rw-r--r-- | net/bridge/br_stp_if.c | 9 | ||||
| -rw-r--r-- | net/can/af_can.c | 9 | ||||
| -rw-r--r-- | net/can/bcm.c | 4 | ||||
| -rw-r--r-- | net/can/raw.c | 4 | ||||
| -rw-r--r-- | net/core/dev.c | 55 | ||||
| -rw-r--r-- | net/core/ethtool.c | 17 | ||||
| -rw-r--r-- | net/ipv4/fib_trie.c | 4 | ||||
| -rw-r--r-- | net/ipv4/ip_options.c | 6 | ||||
| -rw-r--r-- | net/ipv4/raw.c | 1 | ||||
| -rw-r--r-- | net/ipv6/ip6mr.c | 2 | ||||
| -rw-r--r-- | net/irda/iriap.c | 6 | ||||
| -rw-r--r-- | net/irda/irnet/irnet_ppp.c | 3 | ||||
| -rw-r--r-- | net/rose/af_rose.c | 8 | ||||
| -rw-r--r-- | net/rose/rose_loopback.c | 13 | ||||
| -rw-r--r-- | net/rose/rose_route.c | 20 | ||||
| -rw-r--r-- | net/rose/rose_subr.c | 101 | ||||
| -rw-r--r-- | net/xfrm/xfrm_input.c | 4 | ||||
| -rw-r--r-- | net/xfrm/xfrm_output.c | 4 | ||||
| -rw-r--r-- | net/xfrm/xfrm_replay.c | 17 | ||||
| -rw-r--r-- | net/xfrm/xfrm_state.c | 6 | ||||
| -rw-r--r-- | net/xfrm/xfrm_user.c | 24 |
23 files changed, 201 insertions, 124 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index dce8f0009a12..718b60366dfe 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -389,6 +389,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 389 | { | 389 | { |
| 390 | struct net_bridge_port *p; | 390 | struct net_bridge_port *p; |
| 391 | int err = 0; | 391 | int err = 0; |
| 392 | bool changed_addr; | ||
| 392 | 393 | ||
| 393 | /* Don't allow bridging non-ethernet like devices */ | 394 | /* Don't allow bridging non-ethernet like devices */ |
| 394 | if ((dev->flags & IFF_LOOPBACK) || | 395 | if ((dev->flags & IFF_LOOPBACK) || |
| @@ -446,7 +447,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 446 | list_add_rcu(&p->list, &br->port_list); | 447 | list_add_rcu(&p->list, &br->port_list); |
| 447 | 448 | ||
| 448 | spin_lock_bh(&br->lock); | 449 | spin_lock_bh(&br->lock); |
| 449 | br_stp_recalculate_bridge_id(br); | 450 | changed_addr = br_stp_recalculate_bridge_id(br); |
| 450 | br_features_recompute(br); | 451 | br_features_recompute(br); |
| 451 | 452 | ||
| 452 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
| @@ -456,6 +457,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 456 | 457 | ||
| 457 | br_ifinfo_notify(RTM_NEWLINK, p); | 458 | br_ifinfo_notify(RTM_NEWLINK, p); |
| 458 | 459 | ||
| 460 | if (changed_addr) | ||
| 461 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | ||
| 462 | |||
| 459 | dev_set_mtu(br->dev, br_min_mtu(br)); | 463 | dev_set_mtu(br->dev, br_min_mtu(br)); |
| 460 | 464 | ||
| 461 | kobject_uevent(&p->kobj, KOBJ_ADD); | 465 | kobject_uevent(&p->kobj, KOBJ_ADD); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 19e2f46ed086..387013d33745 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -497,7 +497,7 @@ extern void br_stp_disable_bridge(struct net_bridge *br); | |||
| 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); | 497 | extern void br_stp_set_enabled(struct net_bridge *br, unsigned long val); |
| 498 | extern void br_stp_enable_port(struct net_bridge_port *p); | 498 | extern void br_stp_enable_port(struct net_bridge_port *p); |
| 499 | extern void br_stp_disable_port(struct net_bridge_port *p); | 499 | extern void br_stp_disable_port(struct net_bridge_port *p); |
| 500 | extern void br_stp_recalculate_bridge_id(struct net_bridge *br); | 500 | extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); |
| 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | 501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); |
| 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
| 503 | u16 newprio); | 503 | u16 newprio); |
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 79372d4a4055..5593f5aec942 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
| @@ -204,7 +204,7 @@ void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) | |||
| 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; | 204 | static const unsigned short br_mac_zero_aligned[ETH_ALEN >> 1]; |
| 205 | 205 | ||
| 206 | /* called under bridge lock */ | 206 | /* called under bridge lock */ |
| 207 | void br_stp_recalculate_bridge_id(struct net_bridge *br) | 207 | bool br_stp_recalculate_bridge_id(struct net_bridge *br) |
| 208 | { | 208 | { |
| 209 | const unsigned char *br_mac_zero = | 209 | const unsigned char *br_mac_zero = |
| 210 | (const unsigned char *)br_mac_zero_aligned; | 210 | (const unsigned char *)br_mac_zero_aligned; |
| @@ -222,8 +222,11 @@ void br_stp_recalculate_bridge_id(struct net_bridge *br) | |||
| 222 | 222 | ||
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | if (compare_ether_addr(br->bridge_id.addr, addr)) | 225 | if (compare_ether_addr(br->bridge_id.addr, addr) == 0) |
| 226 | br_stp_change_bridge_id(br, addr); | 226 | return false; /* no change */ |
| 227 | |||
| 228 | br_stp_change_bridge_id(br, addr); | ||
| 229 | return true; | ||
| 227 | } | 230 | } |
| 228 | 231 | ||
| 229 | /* called under bridge lock */ | 232 | /* called under bridge lock */ |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 702be5a2c956..733d66f1b05a 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
| @@ -95,7 +95,7 @@ struct s_pstats can_pstats; /* receive list statistics */ | |||
| 95 | * af_can socket functions | 95 | * af_can socket functions |
| 96 | */ | 96 | */ |
| 97 | 97 | ||
| 98 | static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 98 | int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
| 99 | { | 99 | { |
| 100 | struct sock *sk = sock->sk; | 100 | struct sock *sk = sock->sk; |
| 101 | 101 | ||
| @@ -108,6 +108,7 @@ static int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 108 | return -ENOIOCTLCMD; | 108 | return -ENOIOCTLCMD; |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| 111 | EXPORT_SYMBOL(can_ioctl); | ||
| 111 | 112 | ||
| 112 | static void can_sock_destruct(struct sock *sk) | 113 | static void can_sock_destruct(struct sock *sk) |
| 113 | { | 114 | { |
| @@ -698,13 +699,9 @@ int can_proto_register(struct can_proto *cp) | |||
| 698 | printk(KERN_ERR "can: protocol %d already registered\n", | 699 | printk(KERN_ERR "can: protocol %d already registered\n", |
| 699 | proto); | 700 | proto); |
| 700 | err = -EBUSY; | 701 | err = -EBUSY; |
| 701 | } else { | 702 | } else |
| 702 | proto_tab[proto] = cp; | 703 | proto_tab[proto] = cp; |
| 703 | 704 | ||
| 704 | /* use generic ioctl function if not defined by module */ | ||
| 705 | if (!cp->ops->ioctl) | ||
| 706 | cp->ops->ioctl = can_ioctl; | ||
| 707 | } | ||
| 708 | spin_unlock(&proto_tab_lock); | 705 | spin_unlock(&proto_tab_lock); |
| 709 | 706 | ||
| 710 | if (err < 0) | 707 | if (err < 0) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 092dc88a7c64..871a0ad51025 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
| @@ -1569,7 +1569,7 @@ static int bcm_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1569 | return size; | 1569 | return size; |
| 1570 | } | 1570 | } |
| 1571 | 1571 | ||
| 1572 | static struct proto_ops bcm_ops __read_mostly = { | 1572 | static const struct proto_ops bcm_ops = { |
| 1573 | .family = PF_CAN, | 1573 | .family = PF_CAN, |
| 1574 | .release = bcm_release, | 1574 | .release = bcm_release, |
| 1575 | .bind = sock_no_bind, | 1575 | .bind = sock_no_bind, |
| @@ -1578,7 +1578,7 @@ static struct proto_ops bcm_ops __read_mostly = { | |||
| 1578 | .accept = sock_no_accept, | 1578 | .accept = sock_no_accept, |
| 1579 | .getname = sock_no_getname, | 1579 | .getname = sock_no_getname, |
| 1580 | .poll = datagram_poll, | 1580 | .poll = datagram_poll, |
| 1581 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 1581 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
| 1582 | .listen = sock_no_listen, | 1582 | .listen = sock_no_listen, |
| 1583 | .shutdown = sock_no_shutdown, | 1583 | .shutdown = sock_no_shutdown, |
| 1584 | .setsockopt = sock_no_setsockopt, | 1584 | .setsockopt = sock_no_setsockopt, |
diff --git a/net/can/raw.c b/net/can/raw.c index 883e9d74fddf..649acfa7c70a 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -742,7 +742,7 @@ static int raw_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 742 | return size; | 742 | return size; |
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | static struct proto_ops raw_ops __read_mostly = { | 745 | static const struct proto_ops raw_ops = { |
| 746 | .family = PF_CAN, | 746 | .family = PF_CAN, |
| 747 | .release = raw_release, | 747 | .release = raw_release, |
| 748 | .bind = raw_bind, | 748 | .bind = raw_bind, |
| @@ -751,7 +751,7 @@ static struct proto_ops raw_ops __read_mostly = { | |||
| 751 | .accept = sock_no_accept, | 751 | .accept = sock_no_accept, |
| 752 | .getname = raw_getname, | 752 | .getname = raw_getname, |
| 753 | .poll = datagram_poll, | 753 | .poll = datagram_poll, |
| 754 | .ioctl = NULL, /* use can_ioctl() from af_can.c */ | 754 | .ioctl = can_ioctl, /* use can_ioctl() from af_can.c */ |
| 755 | .listen = sock_no_listen, | 755 | .listen = sock_no_listen, |
| 756 | .shutdown = sock_no_shutdown, | 756 | .shutdown = sock_no_shutdown, |
| 757 | .setsockopt = raw_setsockopt, | 757 | .setsockopt = raw_setsockopt, |
diff --git a/net/core/dev.c b/net/core/dev.c index f453370131a0..563ddc28139d 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1140,9 +1140,6 @@ static int __dev_open(struct net_device *dev) | |||
| 1140 | 1140 | ||
| 1141 | ASSERT_RTNL(); | 1141 | ASSERT_RTNL(); |
| 1142 | 1142 | ||
| 1143 | /* | ||
| 1144 | * Is it even present? | ||
| 1145 | */ | ||
| 1146 | if (!netif_device_present(dev)) | 1143 | if (!netif_device_present(dev)) |
| 1147 | return -ENODEV; | 1144 | return -ENODEV; |
| 1148 | 1145 | ||
| @@ -1151,9 +1148,6 @@ static int __dev_open(struct net_device *dev) | |||
| 1151 | if (ret) | 1148 | if (ret) |
| 1152 | return ret; | 1149 | return ret; |
| 1153 | 1150 | ||
| 1154 | /* | ||
| 1155 | * Call device private open method | ||
| 1156 | */ | ||
| 1157 | set_bit(__LINK_STATE_START, &dev->state); | 1151 | set_bit(__LINK_STATE_START, &dev->state); |
| 1158 | 1152 | ||
| 1159 | if (ops->ndo_validate_addr) | 1153 | if (ops->ndo_validate_addr) |
| @@ -1162,31 +1156,12 @@ static int __dev_open(struct net_device *dev) | |||
| 1162 | if (!ret && ops->ndo_open) | 1156 | if (!ret && ops->ndo_open) |
| 1163 | ret = ops->ndo_open(dev); | 1157 | ret = ops->ndo_open(dev); |
| 1164 | 1158 | ||
| 1165 | /* | ||
| 1166 | * If it went open OK then: | ||
| 1167 | */ | ||
| 1168 | |||
| 1169 | if (ret) | 1159 | if (ret) |
| 1170 | clear_bit(__LINK_STATE_START, &dev->state); | 1160 | clear_bit(__LINK_STATE_START, &dev->state); |
| 1171 | else { | 1161 | else { |
| 1172 | /* | ||
| 1173 | * Set the flags. | ||
| 1174 | */ | ||
| 1175 | dev->flags |= IFF_UP; | 1162 | dev->flags |= IFF_UP; |
| 1176 | |||
| 1177 | /* | ||
| 1178 | * Enable NET_DMA | ||
| 1179 | */ | ||
| 1180 | net_dmaengine_get(); | 1163 | net_dmaengine_get(); |
| 1181 | |||
| 1182 | /* | ||
| 1183 | * Initialize multicasting status | ||
| 1184 | */ | ||
| 1185 | dev_set_rx_mode(dev); | 1164 | dev_set_rx_mode(dev); |
| 1186 | |||
| 1187 | /* | ||
| 1188 | * Wakeup transmit queue engine | ||
| 1189 | */ | ||
| 1190 | dev_activate(dev); | 1165 | dev_activate(dev); |
| 1191 | } | 1166 | } |
| 1192 | 1167 | ||
| @@ -1209,22 +1184,13 @@ int dev_open(struct net_device *dev) | |||
| 1209 | { | 1184 | { |
| 1210 | int ret; | 1185 | int ret; |
| 1211 | 1186 | ||
| 1212 | /* | ||
| 1213 | * Is it already up? | ||
| 1214 | */ | ||
| 1215 | if (dev->flags & IFF_UP) | 1187 | if (dev->flags & IFF_UP) |
| 1216 | return 0; | 1188 | return 0; |
| 1217 | 1189 | ||
| 1218 | /* | ||
| 1219 | * Open device | ||
| 1220 | */ | ||
| 1221 | ret = __dev_open(dev); | 1190 | ret = __dev_open(dev); |
| 1222 | if (ret < 0) | 1191 | if (ret < 0) |
| 1223 | return ret; | 1192 | return ret; |
| 1224 | 1193 | ||
| 1225 | /* | ||
| 1226 | * ... and announce new interface. | ||
| 1227 | */ | ||
| 1228 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1194 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
| 1229 | call_netdevice_notifiers(NETDEV_UP, dev); | 1195 | call_netdevice_notifiers(NETDEV_UP, dev); |
| 1230 | 1196 | ||
| @@ -1240,10 +1206,6 @@ static int __dev_close_many(struct list_head *head) | |||
| 1240 | might_sleep(); | 1206 | might_sleep(); |
| 1241 | 1207 | ||
| 1242 | list_for_each_entry(dev, head, unreg_list) { | 1208 | list_for_each_entry(dev, head, unreg_list) { |
| 1243 | /* | ||
| 1244 | * Tell people we are going down, so that they can | ||
| 1245 | * prepare to death, when device is still operating. | ||
| 1246 | */ | ||
| 1247 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); | 1209 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); |
| 1248 | 1210 | ||
| 1249 | clear_bit(__LINK_STATE_START, &dev->state); | 1211 | clear_bit(__LINK_STATE_START, &dev->state); |
| @@ -1272,15 +1234,7 @@ static int __dev_close_many(struct list_head *head) | |||
| 1272 | if (ops->ndo_stop) | 1234 | if (ops->ndo_stop) |
| 1273 | ops->ndo_stop(dev); | 1235 | ops->ndo_stop(dev); |
| 1274 | 1236 | ||
| 1275 | /* | ||
| 1276 | * Device is now down. | ||
| 1277 | */ | ||
| 1278 | |||
| 1279 | dev->flags &= ~IFF_UP; | 1237 | dev->flags &= ~IFF_UP; |
| 1280 | |||
| 1281 | /* | ||
| 1282 | * Shutdown NET_DMA | ||
| 1283 | */ | ||
| 1284 | net_dmaengine_put(); | 1238 | net_dmaengine_put(); |
| 1285 | } | 1239 | } |
| 1286 | 1240 | ||
| @@ -1309,9 +1263,6 @@ static int dev_close_many(struct list_head *head) | |||
| 1309 | 1263 | ||
| 1310 | __dev_close_many(head); | 1264 | __dev_close_many(head); |
| 1311 | 1265 | ||
| 1312 | /* | ||
| 1313 | * Tell people we are down | ||
| 1314 | */ | ||
| 1315 | list_for_each_entry(dev, head, unreg_list) { | 1266 | list_for_each_entry(dev, head, unreg_list) { |
| 1316 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1267 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); |
| 1317 | call_netdevice_notifiers(NETDEV_DOWN, dev); | 1268 | call_netdevice_notifiers(NETDEV_DOWN, dev); |
| @@ -1371,11 +1322,6 @@ EXPORT_SYMBOL(dev_disable_lro); | |||
| 1371 | 1322 | ||
| 1372 | static int dev_boot_phase = 1; | 1323 | static int dev_boot_phase = 1; |
| 1373 | 1324 | ||
| 1374 | /* | ||
| 1375 | * Device change register/unregister. These are not inline or static | ||
| 1376 | * as we export them to the world. | ||
| 1377 | */ | ||
| 1378 | |||
| 1379 | /** | 1325 | /** |
| 1380 | * register_netdevice_notifier - register a network notifier block | 1326 | * register_netdevice_notifier - register a network notifier block |
| 1381 | * @nb: notifier | 1327 | * @nb: notifier |
| @@ -1477,6 +1423,7 @@ int call_netdevice_notifiers(unsigned long val, struct net_device *dev) | |||
| 1477 | ASSERT_RTNL(); | 1423 | ASSERT_RTNL(); |
| 1478 | return raw_notifier_call_chain(&netdev_chain, val, dev); | 1424 | return raw_notifier_call_chain(&netdev_chain, val, dev); |
| 1479 | } | 1425 | } |
| 1426 | EXPORT_SYMBOL(call_netdevice_notifiers); | ||
| 1480 | 1427 | ||
| 1481 | /* When > 0 there are consumers of rx skb time stamps */ | 1428 | /* When > 0 there are consumers of rx skb time stamps */ |
| 1482 | static atomic_t netstamp_needed = ATOMIC_INIT(0); | 1429 | static atomic_t netstamp_needed = ATOMIC_INIT(0); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 24bd57493c0d..74ead9eca126 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -141,9 +141,24 @@ u32 ethtool_op_get_flags(struct net_device *dev) | |||
| 141 | } | 141 | } |
| 142 | EXPORT_SYMBOL(ethtool_op_get_flags); | 142 | EXPORT_SYMBOL(ethtool_op_get_flags); |
| 143 | 143 | ||
| 144 | /* Check if device can enable (or disable) particular feature coded in "data" | ||
| 145 | * argument. Flags "supported" describe features that can be toggled by device. | ||
| 146 | * If feature can not be toggled, it state (enabled or disabled) must match | ||
| 147 | * hardcoded device features state, otherwise flags are marked as invalid. | ||
| 148 | */ | ||
| 149 | bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported) | ||
| 150 | { | ||
| 151 | u32 features = dev->features & flags_dup_features; | ||
| 152 | /* "data" can contain only flags_dup_features bits, | ||
| 153 | * see __ethtool_set_flags */ | ||
| 154 | |||
| 155 | return (features & ~supported) != (data & ~supported); | ||
| 156 | } | ||
| 157 | EXPORT_SYMBOL(ethtool_invalid_flags); | ||
| 158 | |||
| 144 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) | 159 | int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported) |
| 145 | { | 160 | { |
| 146 | if (data & ~supported) | 161 | if (ethtool_invalid_flags(dev, data, supported)) |
| 147 | return -EINVAL; | 162 | return -EINVAL; |
| 148 | 163 | ||
| 149 | dev->features = ((dev->features & ~flags_dup_features) | | 164 | dev->features = ((dev->features & ~flags_dup_features) | |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 90a3ff605591..b92c86f6e9b3 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1365,9 +1365,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l, | |||
| 1365 | err = fib_props[fa->fa_type].error; | 1365 | err = fib_props[fa->fa_type].error; |
| 1366 | if (err) { | 1366 | if (err) { |
| 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 1367 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
| 1368 | t->stats.semantic_match_miss++; | 1368 | t->stats.semantic_match_passed++; |
| 1369 | #endif | 1369 | #endif |
| 1370 | return 1; | 1370 | return err; |
| 1371 | } | 1371 | } |
| 1372 | if (fi->fib_flags & RTNH_F_DEAD) | 1372 | if (fi->fib_flags & RTNH_F_DEAD) |
| 1373 | continue; | 1373 | continue; |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 1906fa35860c..28a736f3442f 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
| @@ -140,11 +140,11 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
| 140 | } else { | 140 | } else { |
| 141 | dopt->ts_needtime = 0; | 141 | dopt->ts_needtime = 0; |
| 142 | 142 | ||
| 143 | if (soffset + 8 <= optlen) { | 143 | if (soffset + 7 <= optlen) { |
| 144 | __be32 addr; | 144 | __be32 addr; |
| 145 | 145 | ||
| 146 | memcpy(&addr, sptr+soffset-1, 4); | 146 | memcpy(&addr, dptr+soffset-1, 4); |
| 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_LOCAL) { | 147 | if (inet_addr_type(dev_net(skb_dst(skb)->dev), addr) != RTN_UNICAST) { |
| 148 | dopt->ts_needtime = 1; | 148 | dopt->ts_needtime = 1; |
| 149 | soffset += 8; | 149 | soffset += 8; |
| 150 | } | 150 | } |
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e837ffd3edc3..2d3c72e5bbbf 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
| @@ -569,6 +569,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); |
| 570 | if (IS_ERR(rt)) { | 570 | if (IS_ERR(rt)) { |
| 571 | err = PTR_ERR(rt); | 571 | err = PTR_ERR(rt); |
| 572 | rt = NULL; | ||
| 572 | goto done; | 573 | goto done; |
| 573 | } | 574 | } |
| 574 | } | 575 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 7ff0343e05c7..29e48593bf22 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -663,7 +663,7 @@ static int pim6_rcv(struct sk_buff *skb) | |||
| 663 | skb_pull(skb, (u8 *)encap - skb->data); | 663 | skb_pull(skb, (u8 *)encap - skb->data); |
| 664 | skb_reset_network_header(skb); | 664 | skb_reset_network_header(skb); |
| 665 | skb->protocol = htons(ETH_P_IPV6); | 665 | skb->protocol = htons(ETH_P_IPV6); |
| 666 | skb->ip_summed = 0; | 666 | skb->ip_summed = CHECKSUM_NONE; |
| 667 | skb->pkt_type = PACKET_HOST; | 667 | skb->pkt_type = PACKET_HOST; |
| 668 | 668 | ||
| 669 | skb_tunnel_rx(skb, reg_dev); | 669 | skb_tunnel_rx(skb, reg_dev); |
diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 5b743bdd89ba..36477538cea8 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c | |||
| @@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self, | |||
| 656 | n = 1; | 656 | n = 1; |
| 657 | 657 | ||
| 658 | name_len = fp[n++]; | 658 | name_len = fp[n++]; |
| 659 | |||
| 660 | IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;); | ||
| 661 | |||
| 659 | memcpy(name, fp+n, name_len); n+=name_len; | 662 | memcpy(name, fp+n, name_len); n+=name_len; |
| 660 | name[name_len] = '\0'; | 663 | name[name_len] = '\0'; |
| 661 | 664 | ||
| 662 | attr_len = fp[n++]; | 665 | attr_len = fp[n++]; |
| 666 | |||
| 667 | IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;); | ||
| 668 | |||
| 663 | memcpy(attr, fp+n, attr_len); n+=attr_len; | 669 | memcpy(attr, fp+n, attr_len); n+=attr_len; |
| 664 | attr[attr_len] = '\0'; | 670 | attr[attr_len] = '\0'; |
| 665 | 671 | ||
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c index 7c567b8aa89a..2bb2beb6a373 100644 --- a/net/irda/irnet/irnet_ppp.c +++ b/net/irda/irnet/irnet_ppp.c | |||
| @@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap, | |||
| 105 | while(isspace(start[length - 1])) | 105 | while(isspace(start[length - 1])) |
| 106 | length--; | 106 | length--; |
| 107 | 107 | ||
| 108 | DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5, | ||
| 109 | -EINVAL, CTRL_ERROR, "Invalid nickname.\n"); | ||
| 110 | |||
| 108 | /* Copy the name for later reuse */ | 111 | /* Copy the name for later reuse */ |
| 109 | memcpy(ap->rname, start + 5, length - 5); | 112 | memcpy(ap->rname, start + 5, length - 5); |
| 110 | ap->rname[length - 5] = '\0'; | 113 | ap->rname[length - 5] = '\0'; |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 5ee0c62046a0..a80aef6e3d1f 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
| @@ -978,7 +978,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
| 978 | struct sock *make; | 978 | struct sock *make; |
| 979 | struct rose_sock *make_rose; | 979 | struct rose_sock *make_rose; |
| 980 | struct rose_facilities_struct facilities; | 980 | struct rose_facilities_struct facilities; |
| 981 | int n, len; | 981 | int n; |
| 982 | 982 | ||
| 983 | skb->sk = NULL; /* Initially we don't know who it's for */ | 983 | skb->sk = NULL; /* Initially we don't know who it's for */ |
| 984 | 984 | ||
| @@ -987,9 +987,9 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
| 987 | */ | 987 | */ |
| 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 988 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
| 989 | 989 | ||
| 990 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | 990 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
| 991 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | 991 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, |
| 992 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 992 | &facilities)) { |
| 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); | 993 | rose_transmit_clear_request(neigh, lci, ROSE_INVALID_FACILITY, 76); |
| 994 | return 0; | 994 | return 0; |
| 995 | } | 995 | } |
diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index ae4a9d99aec7..344456206b70 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c | |||
| @@ -73,9 +73,20 @@ static void rose_loopback_timer(unsigned long param) | |||
| 73 | unsigned int lci_i, lci_o; | 73 | unsigned int lci_i, lci_o; |
| 74 | 74 | ||
| 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { | 75 | while ((skb = skb_dequeue(&loopback_queue)) != NULL) { |
| 76 | if (skb->len < ROSE_MIN_LEN) { | ||
| 77 | kfree_skb(skb); | ||
| 78 | continue; | ||
| 79 | } | ||
| 76 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 80 | lci_i = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 77 | frametype = skb->data[2]; | 81 | frametype = skb->data[2]; |
| 78 | dest = (rose_address *)(skb->data + 4); | 82 | if (frametype == ROSE_CALL_REQUEST && |
| 83 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || | ||
| 84 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
| 85 | ROSE_CALL_REQ_ADDR_LEN_VAL)) { | ||
| 86 | kfree_skb(skb); | ||
| 87 | continue; | ||
| 88 | } | ||
| 89 | dest = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
| 79 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; | 90 | lci_o = ROSE_DEFAULT_MAXVC + 1 - lci_i; |
| 80 | 91 | ||
| 81 | skb_reset_transport_header(skb); | 92 | skb_reset_transport_header(skb); |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 88a77e90e7e8..08dcd2f29cdc 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
| @@ -861,7 +861,7 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 861 | unsigned int lci, new_lci; | 861 | unsigned int lci, new_lci; |
| 862 | unsigned char cause, diagnostic; | 862 | unsigned char cause, diagnostic; |
| 863 | struct net_device *dev; | 863 | struct net_device *dev; |
| 864 | int len, res = 0; | 864 | int res = 0; |
| 865 | char buf[11]; | 865 | char buf[11]; |
| 866 | 866 | ||
| 867 | #if 0 | 867 | #if 0 |
| @@ -869,10 +869,17 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 869 | return res; | 869 | return res; |
| 870 | #endif | 870 | #endif |
| 871 | 871 | ||
| 872 | if (skb->len < ROSE_MIN_LEN) | ||
| 873 | return res; | ||
| 872 | frametype = skb->data[2]; | 874 | frametype = skb->data[2]; |
| 873 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); | 875 | lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF); |
| 874 | src_addr = (rose_address *)(skb->data + 9); | 876 | if (frametype == ROSE_CALL_REQUEST && |
| 875 | dest_addr = (rose_address *)(skb->data + 4); | 877 | (skb->len <= ROSE_CALL_REQ_FACILITIES_OFF || |
| 878 | skb->data[ROSE_CALL_REQ_ADDR_LEN_OFF] != | ||
| 879 | ROSE_CALL_REQ_ADDR_LEN_VAL)) | ||
| 880 | return res; | ||
| 881 | src_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_SRC_ADDR_OFF); | ||
| 882 | dest_addr = (rose_address *)(skb->data + ROSE_CALL_REQ_DEST_ADDR_OFF); | ||
| 876 | 883 | ||
| 877 | spin_lock_bh(&rose_neigh_list_lock); | 884 | spin_lock_bh(&rose_neigh_list_lock); |
| 878 | spin_lock_bh(&rose_route_list_lock); | 885 | spin_lock_bh(&rose_route_list_lock); |
| @@ -1010,12 +1017,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) | |||
| 1010 | goto out; | 1017 | goto out; |
| 1011 | } | 1018 | } |
| 1012 | 1019 | ||
| 1013 | len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1; | ||
| 1014 | len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1; | ||
| 1015 | |||
| 1016 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); | 1020 | memset(&facilities, 0x00, sizeof(struct rose_facilities_struct)); |
| 1017 | 1021 | ||
| 1018 | if (!rose_parse_facilities(skb->data + len + 4, &facilities)) { | 1022 | if (!rose_parse_facilities(skb->data + ROSE_CALL_REQ_FACILITIES_OFF, |
| 1023 | skb->len - ROSE_CALL_REQ_FACILITIES_OFF, | ||
| 1024 | &facilities)) { | ||
| 1019 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); | 1025 | rose_transmit_clear_request(rose_neigh, lci, ROSE_INVALID_FACILITY, 76); |
| 1020 | goto out; | 1026 | goto out; |
| 1021 | } | 1027 | } |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 1734abba26a2..f6c71caa94b9 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
| @@ -142,7 +142,7 @@ void rose_write_internal(struct sock *sk, int frametype) | |||
| 142 | *dptr++ = ROSE_GFI | lci1; | 142 | *dptr++ = ROSE_GFI | lci1; |
| 143 | *dptr++ = lci2; | 143 | *dptr++ = lci2; |
| 144 | *dptr++ = frametype; | 144 | *dptr++ = frametype; |
| 145 | *dptr++ = 0xAA; | 145 | *dptr++ = ROSE_CALL_REQ_ADDR_LEN_VAL; |
| 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); | 146 | memcpy(dptr, &rose->dest_addr, ROSE_ADDR_LEN); |
| 147 | dptr += ROSE_ADDR_LEN; | 147 | dptr += ROSE_ADDR_LEN; |
| 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); | 148 | memcpy(dptr, &rose->source_addr, ROSE_ADDR_LEN); |
| @@ -246,12 +246,16 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
| 246 | do { | 246 | do { |
| 247 | switch (*p & 0xC0) { | 247 | switch (*p & 0xC0) { |
| 248 | case 0x00: | 248 | case 0x00: |
| 249 | if (len < 2) | ||
| 250 | return -1; | ||
| 249 | p += 2; | 251 | p += 2; |
| 250 | n += 2; | 252 | n += 2; |
| 251 | len -= 2; | 253 | len -= 2; |
| 252 | break; | 254 | break; |
| 253 | 255 | ||
| 254 | case 0x40: | 256 | case 0x40: |
| 257 | if (len < 3) | ||
| 258 | return -1; | ||
| 255 | if (*p == FAC_NATIONAL_RAND) | 259 | if (*p == FAC_NATIONAL_RAND) |
| 256 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); | 260 | facilities->rand = ((p[1] << 8) & 0xFF00) + ((p[2] << 0) & 0x00FF); |
| 257 | p += 3; | 261 | p += 3; |
| @@ -260,40 +264,61 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct * | |||
| 260 | break; | 264 | break; |
| 261 | 265 | ||
| 262 | case 0x80: | 266 | case 0x80: |
| 267 | if (len < 4) | ||
| 268 | return -1; | ||
| 263 | p += 4; | 269 | p += 4; |
| 264 | n += 4; | 270 | n += 4; |
| 265 | len -= 4; | 271 | len -= 4; |
| 266 | break; | 272 | break; |
| 267 | 273 | ||
| 268 | case 0xC0: | 274 | case 0xC0: |
| 275 | if (len < 2) | ||
| 276 | return -1; | ||
| 269 | l = p[1]; | 277 | l = p[1]; |
| 278 | if (len < 2 + l) | ||
| 279 | return -1; | ||
| 270 | if (*p == FAC_NATIONAL_DEST_DIGI) { | 280 | if (*p == FAC_NATIONAL_DEST_DIGI) { |
| 271 | if (!fac_national_digis_received) { | 281 | if (!fac_national_digis_received) { |
| 282 | if (l < AX25_ADDR_LEN) | ||
| 283 | return -1; | ||
| 272 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); | 284 | memcpy(&facilities->source_digis[0], p + 2, AX25_ADDR_LEN); |
| 273 | facilities->source_ndigis = 1; | 285 | facilities->source_ndigis = 1; |
| 274 | } | 286 | } |
| 275 | } | 287 | } |
| 276 | else if (*p == FAC_NATIONAL_SRC_DIGI) { | 288 | else if (*p == FAC_NATIONAL_SRC_DIGI) { |
| 277 | if (!fac_national_digis_received) { | 289 | if (!fac_national_digis_received) { |
| 290 | if (l < AX25_ADDR_LEN) | ||
| 291 | return -1; | ||
| 278 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); | 292 | memcpy(&facilities->dest_digis[0], p + 2, AX25_ADDR_LEN); |
| 279 | facilities->dest_ndigis = 1; | 293 | facilities->dest_ndigis = 1; |
| 280 | } | 294 | } |
| 281 | } | 295 | } |
| 282 | else if (*p == FAC_NATIONAL_FAIL_CALL) { | 296 | else if (*p == FAC_NATIONAL_FAIL_CALL) { |
| 297 | if (l < AX25_ADDR_LEN) | ||
| 298 | return -1; | ||
| 283 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); | 299 | memcpy(&facilities->fail_call, p + 2, AX25_ADDR_LEN); |
| 284 | } | 300 | } |
| 285 | else if (*p == FAC_NATIONAL_FAIL_ADD) { | 301 | else if (*p == FAC_NATIONAL_FAIL_ADD) { |
| 302 | if (l < 1 + ROSE_ADDR_LEN) | ||
| 303 | return -1; | ||
| 286 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); | 304 | memcpy(&facilities->fail_addr, p + 3, ROSE_ADDR_LEN); |
| 287 | } | 305 | } |
| 288 | else if (*p == FAC_NATIONAL_DIGIS) { | 306 | else if (*p == FAC_NATIONAL_DIGIS) { |
| 307 | if (l % AX25_ADDR_LEN) | ||
| 308 | return -1; | ||
| 289 | fac_national_digis_received = 1; | 309 | fac_national_digis_received = 1; |
| 290 | facilities->source_ndigis = 0; | 310 | facilities->source_ndigis = 0; |
| 291 | facilities->dest_ndigis = 0; | 311 | facilities->dest_ndigis = 0; |
| 292 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { | 312 | for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) { |
| 293 | if (pt[6] & AX25_HBIT) | 313 | if (pt[6] & AX25_HBIT) { |
| 314 | if (facilities->dest_ndigis >= ROSE_MAX_DIGIS) | ||
| 315 | return -1; | ||
| 294 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); | 316 | memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN); |
| 295 | else | 317 | } else { |
| 318 | if (facilities->source_ndigis >= ROSE_MAX_DIGIS) | ||
| 319 | return -1; | ||
| 296 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); | 320 | memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN); |
| 321 | } | ||
| 297 | } | 322 | } |
| 298 | } | 323 | } |
| 299 | p += l + 2; | 324 | p += l + 2; |
| @@ -314,25 +339,38 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
| 314 | do { | 339 | do { |
| 315 | switch (*p & 0xC0) { | 340 | switch (*p & 0xC0) { |
| 316 | case 0x00: | 341 | case 0x00: |
| 342 | if (len < 2) | ||
| 343 | return -1; | ||
| 317 | p += 2; | 344 | p += 2; |
| 318 | n += 2; | 345 | n += 2; |
| 319 | len -= 2; | 346 | len -= 2; |
| 320 | break; | 347 | break; |
| 321 | 348 | ||
| 322 | case 0x40: | 349 | case 0x40: |
| 350 | if (len < 3) | ||
| 351 | return -1; | ||
| 323 | p += 3; | 352 | p += 3; |
| 324 | n += 3; | 353 | n += 3; |
| 325 | len -= 3; | 354 | len -= 3; |
| 326 | break; | 355 | break; |
| 327 | 356 | ||
| 328 | case 0x80: | 357 | case 0x80: |
| 358 | if (len < 4) | ||
| 359 | return -1; | ||
| 329 | p += 4; | 360 | p += 4; |
| 330 | n += 4; | 361 | n += 4; |
| 331 | len -= 4; | 362 | len -= 4; |
| 332 | break; | 363 | break; |
| 333 | 364 | ||
| 334 | case 0xC0: | 365 | case 0xC0: |
| 366 | if (len < 2) | ||
| 367 | return -1; | ||
| 335 | l = p[1]; | 368 | l = p[1]; |
| 369 | |||
| 370 | /* Prevent overflows*/ | ||
| 371 | if (l < 10 || l > 20) | ||
| 372 | return -1; | ||
| 373 | |||
| 336 | if (*p == FAC_CCITT_DEST_NSAP) { | 374 | if (*p == FAC_CCITT_DEST_NSAP) { |
| 337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 375 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
| 338 | memcpy(callsign, p + 12, l - 10); | 376 | memcpy(callsign, p + 12, l - 10); |
| @@ -355,45 +393,44 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
| 355 | return n; | 393 | return n; |
| 356 | } | 394 | } |
| 357 | 395 | ||
| 358 | int rose_parse_facilities(unsigned char *p, | 396 | int rose_parse_facilities(unsigned char *p, unsigned packet_len, |
| 359 | struct rose_facilities_struct *facilities) | 397 | struct rose_facilities_struct *facilities) |
| 360 | { | 398 | { |
| 361 | int facilities_len, len; | 399 | int facilities_len, len; |
| 362 | 400 | ||
| 363 | facilities_len = *p++; | 401 | facilities_len = *p++; |
| 364 | 402 | ||
| 365 | if (facilities_len == 0) | 403 | if (facilities_len == 0 || (unsigned)facilities_len > packet_len) |
| 366 | return 0; | 404 | return 0; |
| 367 | 405 | ||
| 368 | while (facilities_len > 0) { | 406 | while (facilities_len >= 3 && *p == 0x00) { |
| 369 | if (*p == 0x00) { | 407 | facilities_len--; |
| 370 | facilities_len--; | 408 | p++; |
| 371 | p++; | 409 | |
| 372 | 410 | switch (*p) { | |
| 373 | switch (*p) { | 411 | case FAC_NATIONAL: /* National */ |
| 374 | case FAC_NATIONAL: /* National */ | 412 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); |
| 375 | len = rose_parse_national(p + 1, facilities, facilities_len - 1); | 413 | break; |
| 376 | facilities_len -= len + 1; | 414 | |
| 377 | p += len + 1; | 415 | case FAC_CCITT: /* CCITT */ |
| 378 | break; | 416 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); |
| 379 | 417 | break; | |
| 380 | case FAC_CCITT: /* CCITT */ | 418 | |
| 381 | len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1); | 419 | default: |
| 382 | facilities_len -= len + 1; | 420 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); |
| 383 | p += len + 1; | 421 | len = 1; |
| 384 | break; | 422 | break; |
| 385 | 423 | } | |
| 386 | default: | 424 | |
| 387 | printk(KERN_DEBUG "ROSE: rose_parse_facilities - unknown facilities family %02X\n", *p); | 425 | if (len < 0) |
| 388 | facilities_len--; | 426 | return 0; |
| 389 | p++; | 427 | if (WARN_ON(len >= facilities_len)) |
| 390 | break; | 428 | return 0; |
| 391 | } | 429 | facilities_len -= len + 1; |
| 392 | } else | 430 | p += len + 1; |
| 393 | break; /* Error in facilities format */ | ||
| 394 | } | 431 | } |
| 395 | 432 | ||
| 396 | return 1; | 433 | return facilities_len == 0; |
| 397 | } | 434 | } |
| 398 | 435 | ||
| 399 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) | 436 | static int rose_create_facilities(unsigned char *buffer, struct rose_sock *rose) |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 872065ca7f8c..a026b0ef2443 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
| @@ -173,7 +173,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 173 | goto drop_unlock; | 173 | goto drop_unlock; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | if (x->props.replay_window && x->repl->check(x, skb, seq)) { | 176 | if (x->repl->check(x, skb, seq)) { |
| 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); | 177 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); |
| 178 | goto drop_unlock; | 178 | goto drop_unlock; |
| 179 | } | 179 | } |
| @@ -190,6 +190,8 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; | 190 | XFRM_SKB_CB(skb)->seq.input.low = seq; |
| 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; | 191 | XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; |
| 192 | 192 | ||
| 193 | skb_dst_force(skb); | ||
| 194 | |||
| 193 | nexthdr = x->type->input(x, skb); | 195 | nexthdr = x->type->input(x, skb); |
| 194 | 196 | ||
| 195 | if (nexthdr == -EINPROGRESS) | 197 | if (nexthdr == -EINPROGRESS) |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 1aba03f449cc..47bacd8c0250 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -78,6 +78,8 @@ static int xfrm_output_one(struct sk_buff *skb, int err) | |||
| 78 | 78 | ||
| 79 | spin_unlock_bh(&x->lock); | 79 | spin_unlock_bh(&x->lock); |
| 80 | 80 | ||
| 81 | skb_dst_force(skb); | ||
| 82 | |||
| 81 | err = x->type->output(x, skb); | 83 | err = x->type->output(x, skb); |
| 82 | if (err == -EINPROGRESS) | 84 | if (err == -EINPROGRESS) |
| 83 | goto out_exit; | 85 | goto out_exit; |
| @@ -94,7 +96,7 @@ resume: | |||
| 94 | err = -EHOSTUNREACH; | 96 | err = -EHOSTUNREACH; |
| 95 | goto error_nolock; | 97 | goto error_nolock; |
| 96 | } | 98 | } |
| 97 | skb_dst_set(skb, dst_clone(dst)); | 99 | skb_dst_set(skb, dst); |
| 98 | x = dst->xfrm; | 100 | x = dst->xfrm; |
| 99 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); | 101 | } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); |
| 100 | 102 | ||
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f5be5b15740..f218385950ca 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
| @@ -118,6 +118,9 @@ static int xfrm_replay_check(struct xfrm_state *x, | |||
| 118 | u32 diff; | 118 | u32 diff; |
| 119 | u32 seq = ntohl(net_seq); | 119 | u32 seq = ntohl(net_seq); |
| 120 | 120 | ||
| 121 | if (!x->props.replay_window) | ||
| 122 | return 0; | ||
| 123 | |||
| 121 | if (unlikely(seq == 0)) | 124 | if (unlikely(seq == 0)) |
| 122 | goto err; | 125 | goto err; |
| 123 | 126 | ||
| @@ -193,9 +196,14 @@ static int xfrm_replay_check_bmp(struct xfrm_state *x, | |||
| 193 | { | 196 | { |
| 194 | unsigned int bitnr, nr; | 197 | unsigned int bitnr, nr; |
| 195 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 198 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 199 | u32 pos; | ||
| 196 | u32 seq = ntohl(net_seq); | 200 | u32 seq = ntohl(net_seq); |
| 197 | u32 diff = replay_esn->seq - seq; | 201 | u32 diff = replay_esn->seq - seq; |
| 198 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | 202 | |
| 203 | if (!replay_esn->replay_window) | ||
| 204 | return 0; | ||
| 205 | |||
| 206 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 199 | 207 | ||
| 200 | if (unlikely(seq == 0)) | 208 | if (unlikely(seq == 0)) |
| 201 | goto err; | 209 | goto err; |
| @@ -373,12 +381,17 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, | |||
| 373 | unsigned int bitnr, nr; | 381 | unsigned int bitnr, nr; |
| 374 | u32 diff; | 382 | u32 diff; |
| 375 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; | 383 | struct xfrm_replay_state_esn *replay_esn = x->replay_esn; |
| 384 | u32 pos; | ||
| 376 | u32 seq = ntohl(net_seq); | 385 | u32 seq = ntohl(net_seq); |
| 377 | u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 378 | u32 wsize = replay_esn->replay_window; | 386 | u32 wsize = replay_esn->replay_window; |
| 379 | u32 top = replay_esn->seq; | 387 | u32 top = replay_esn->seq; |
| 380 | u32 bottom = top - wsize + 1; | 388 | u32 bottom = top - wsize + 1; |
| 381 | 389 | ||
| 390 | if (!wsize) | ||
| 391 | return 0; | ||
| 392 | |||
| 393 | pos = (replay_esn->seq - 1) % replay_esn->replay_window; | ||
| 394 | |||
| 382 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && | 395 | if (unlikely(seq == 0 && replay_esn->seq_hi == 0 && |
| 383 | (replay_esn->seq < replay_esn->replay_window - 1))) | 396 | (replay_esn->seq < replay_esn->replay_window - 1))) |
| 384 | goto err; | 397 | goto err; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index f83a3d1da81b..dd78536d40de 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -1181,6 +1181,12 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1181 | goto error; | 1181 | goto error; |
| 1182 | } | 1182 | } |
| 1183 | 1183 | ||
| 1184 | if (orig->replay_esn) { | ||
| 1185 | err = xfrm_replay_clone(x, orig); | ||
| 1186 | if (err) | ||
| 1187 | goto error; | ||
| 1188 | } | ||
| 1189 | |||
| 1184 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1190 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
| 1185 | 1191 | ||
| 1186 | err = xfrm_init_state(x); | 1192 | err = xfrm_init_state(x); |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index fc152d28753c..3d15d3e1b2c4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -127,6 +127,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
| 127 | if (!rt) | 127 | if (!rt) |
| 128 | return 0; | 128 | return 0; |
| 129 | 129 | ||
| 130 | if (p->id.proto != IPPROTO_ESP) | ||
| 131 | return -EINVAL; | ||
| 132 | |||
| 130 | if (p->replay_window != 0) | 133 | if (p->replay_window != 0) |
| 131 | return -EINVAL; | 134 | return -EINVAL; |
| 132 | 135 | ||
| @@ -360,6 +363,23 @@ static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props, | |||
| 360 | return 0; | 363 | return 0; |
| 361 | } | 364 | } |
| 362 | 365 | ||
| 366 | static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_esn, | ||
| 367 | struct nlattr *rp) | ||
| 368 | { | ||
| 369 | struct xfrm_replay_state_esn *up; | ||
| 370 | |||
| 371 | if (!replay_esn || !rp) | ||
| 372 | return 0; | ||
| 373 | |||
| 374 | up = nla_data(rp); | ||
| 375 | |||
| 376 | if (xfrm_replay_state_esn_len(replay_esn) != | ||
| 377 | xfrm_replay_state_esn_len(up)) | ||
| 378 | return -EINVAL; | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 363 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, | 383 | static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn, |
| 364 | struct xfrm_replay_state_esn **preplay_esn, | 384 | struct xfrm_replay_state_esn **preplay_esn, |
| 365 | struct nlattr *rta) | 385 | struct nlattr *rta) |
| @@ -1766,6 +1786,10 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 1766 | if (x->km.state != XFRM_STATE_VALID) | 1786 | if (x->km.state != XFRM_STATE_VALID) |
| 1767 | goto out; | 1787 | goto out; |
| 1768 | 1788 | ||
| 1789 | err = xfrm_replay_verify_len(x->replay_esn, rp); | ||
| 1790 | if (err) | ||
| 1791 | goto out; | ||
| 1792 | |||
| 1769 | spin_lock_bh(&x->lock); | 1793 | spin_lock_bh(&x->lock); |
| 1770 | xfrm_update_ae_params(x, attrs); | 1794 | xfrm_update_ae_params(x, attrs); |
| 1771 | spin_unlock_bh(&x->lock); | 1795 | spin_unlock_bh(&x->lock); |
