X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=net%2Fipx%2Faf_ipx.c;h=1627050e29fd76b44438c086aa69fcc7c8f93d6b;hb=2e613e7f69226bd020987bbf0c2ee251c019ab33;hp=c272a38af325ae792355f281baf39866d9bbf0b8;hpb=4833ed094097323f5f219820f6ebdc8dd66f501f;p=safe%2Fjmp%2Flinux-2.6 diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index c272a38..1627050 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -11,7 +11,7 @@ * work I am currently employed to do there. * * All the material in this file is subject to the Gnu license version 2. - * Neither Alan Cox nor the Swansea University Computer Society admit + * Neither Alan Cox nor the Swansea University Computer Society admit * liability nor provide warranty for any of this software. This material * is provided as is and at no charge. * @@ -87,16 +87,11 @@ extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, unsigned char *node); extern void ipxrtr_del_routes(struct ipx_interface *intrfc); extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, - struct iovec *iov, int len, int noblock); + struct iovec *iov, size_t len, int noblock); extern int ipxrtr_route_skb(struct sk_buff *skb); extern struct ipx_route *ipxrtr_lookup(__be32 net); extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg); -#undef IPX_REFCNT_DEBUG -#ifdef IPX_REFCNT_DEBUG -atomic_t ipx_sock_nr; -#endif - struct ipx_interface *ipx_interfaces_head(void) { struct ipx_interface *rc = NULL; @@ -151,18 +146,11 @@ static void ipx_destroy_socket(struct sock *sk) { ipx_remove_socket(sk); skb_queue_purge(&sk->sk_receive_queue); -#ifdef IPX_REFCNT_DEBUG - atomic_dec(&ipx_sock_nr); - printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk, - atomic_read(&ipx_sock_nr)); - if (atomic_read(&sk->sk_refcnt) != 1) - printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n", - sk, atomic_read(&sk->sk_refcnt)); -#endif + sk_refcnt_debug_dec(sk); sock_put(sk); } -/* +/* * The following code is used to support IPX Interfaces (IPXITF). An * IPX interface is defined by a physical device and a frame type. */ @@ -347,6 +335,9 @@ static int ipxitf_device_event(struct notifier_block *notifier, struct net_device *dev = ptr; struct ipx_interface *i, *tmp; + if (!net_eq(dev_net(dev), &init_net)) + return NOTIFY_DONE; + if (event != NETDEV_DOWN && event != NETDEV_UP) goto out; @@ -369,7 +360,7 @@ static __exit void ipxitf_cleanup(void) struct ipx_interface *i, *tmp; spin_lock_bh(&ipx_interfaces_lock); - list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) __ipxitf_put(i); spin_unlock_bh(&ipx_interfaces_lock); } @@ -446,10 +437,10 @@ static struct sock *ncp_connection_hack(struct ipx_interface *intrfc, * You might call this a hack, but believe me, you do not want a * complete NCP layer in the kernel, and this is VERY fast as well. */ struct sock *sk = NULL; - int connection = 0; + int connection = 0; u8 *ncphdr = (u8 *)(ipx + 1); - if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */ + if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */ connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3); else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */ connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8); @@ -482,7 +473,7 @@ static int ipxitf_demux_socket(struct ipx_interface *intrfc, if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) sock1 = ncp_connection_hack(intrfc, ipx); - if (!sock1) + if (!sock1) /* No special socket found, forward the packet the normal way */ sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock); @@ -576,7 +567,9 @@ static struct sk_buff *ipxitf_adjust_skbuff(struct ipx_interface *intrfc, skb2 = alloc_skb(len, GFP_ATOMIC); if (skb2) { skb_reserve(skb2, out_offset); - skb2->nh.raw = skb2->h.raw = skb_put(skb2, skb->len); + skb_reset_network_header(skb2); + skb_reset_transport_header(skb2); + skb_put(skb2, skb->len); memcpy(ipx_hdr(skb2), ipx_hdr(skb), skb->len); memcpy(skb2->cb, skb->cb, sizeof(skb->cb)); } @@ -607,22 +600,22 @@ int ipxitf_send(struct ipx_interface *intrfc, struct sk_buff *skb, char *node) *last_hop = IPX_SKB_CB(skb)->last_hop.netnum; IPX_SKB_CB(skb)->last_hop.index = -1; } - - /* + + /* * We need to know how many skbuffs it will take to send out this * packet to avoid unnecessary copies. */ - - if (!dl || !dev || dev->flags & IFF_LOOPBACK) + + if (!dl || !dev || dev->flags & IFF_LOOPBACK) send_to_wire = 0; /* No non looped */ /* - * See if this should be demuxed to sockets on this interface + * See if this should be demuxed to sockets on this interface * * We want to ensure the original was eaten or that we only use * up clones. */ - + if (ipx->ipx_dest.net == intrfc->if_netnum) { /* * To our own node, loop and free the original. @@ -709,8 +702,8 @@ static int ipxitf_rcv(struct ipx_interface *intrfc, struct sk_buff *skb) /* See if we should update our network number */ if (!intrfc->if_netnum) /* net number of intrfc not known yet */ - ipxitf_discover_netnum(intrfc, skb); - + ipxitf_discover_netnum(intrfc, skb); + IPX_SKB_CB(skb)->last_hop.index = -1; if (ipx->ipx_type == IPX_TYPE_PPROP) { rc = ipxitf_pprop(intrfc, skb); @@ -756,7 +749,7 @@ out_intrfc: static void ipxitf_discover_netnum(struct ipx_interface *intrfc, struct sk_buff *skb) -{ +{ const struct ipx_cb *cb = IPX_SKB_CB(skb); /* see if this is an intra packet: source_net == dest_net */ @@ -793,7 +786,7 @@ static void ipxitf_discover_netnum(struct ipx_interface *intrfc, * it, not even processing it locally, if it has exact %IPX_MAX_PPROP_HOPS we * don't broadcast it, but process it locally. See chapter 5 of Novell's "IPX * RIP and SAP Router Specification", Part Number 107-000029-001. - * + * * If it is valid, check if we have pprop broadcasting enabled by the user, * if not, just return zero for local processing. * @@ -820,7 +813,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) * tctrl <= 15, any data payload... */ if (IPX_SKB_CB(skb)->ipx_tctrl > IPX_MAX_PPROP_HOPS || ntohs(ipx->ipx_pktsize) < sizeof(struct ipxhdr) + - IPX_MAX_PPROP_HOPS * sizeof(u32)) + IPX_MAX_PPROP_HOPS * sizeof(u32)) goto out; /* are we broadcasting this damn thing? */ rc = 0; @@ -831,7 +824,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) * locally. */ if (IPX_SKB_CB(skb)->ipx_tctrl == IPX_MAX_PPROP_HOPS) goto out; - + c = ((u8 *) ipx) + sizeof(struct ipxhdr); l = (__be32 *) c; @@ -851,7 +844,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) /* Except unconfigured interfaces */ if (!ifcs->if_netnum) continue; - + /* That aren't in the list */ if (ifcs == intrfc) continue; @@ -984,7 +977,7 @@ static int ipxitf_create(struct ipx_interface_definition *idef) if (intrfc) ipxitf_put(intrfc); - dev = dev_get_by_name(idef->ipx_device); + dev = dev_get_by_name(&init_net, idef->ipx_device); rc = -ENODEV; if (!dev) goto out; @@ -1003,7 +996,7 @@ static int ipxitf_create(struct ipx_interface_definition *idef) dlink_type = htons(ETH_P_IPX); datalink = pEII_datalink; break; - } else + } else printk(KERN_WARNING "IPX frame type EtherII over " "token-ring is obsolete. Use SNAP " "instead.\n"); @@ -1092,7 +1085,7 @@ static int ipxitf_delete(struct ipx_interface_definition *idef) if (!dlink_type) goto out; - dev = __dev_get_by_name(idef->ipx_device); + dev = __dev_get_by_name(&init_net, idef->ipx_device); rc = -ENODEV; if (!dev) goto out; @@ -1187,7 +1180,7 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) if (copy_from_user(&ifr, arg, sizeof(ifr))) break; sipx = (struct sockaddr_ipx *)&ifr.ifr_addr; - dev = __dev_get_by_name(ifr.ifr_name); + dev = __dev_get_by_name(&init_net, ifr.ifr_name); rc = -ENODEV; if (!dev) break; @@ -1208,14 +1201,14 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) rc = 0; break; } - case SIOCAIPXITFCRT: + case SIOCAIPXITFCRT: rc = -EFAULT; if (get_user(val, (unsigned char __user *) arg)) break; rc = 0; ipxcfg_auto_create_interfaces = val; break; - case SIOCAIPXPRISLT: + case SIOCAIPXPRISLT: rc = -EFAULT; if (get_user(val, (unsigned char __user *) arg)) break; @@ -1230,31 +1223,31 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg) /* * Checksum routine for IPX */ - + /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */ /* This functions should *not* mess with packet contents */ -__u16 ipx_cksum(struct ipxhdr *packet, int length) +__be16 ipx_cksum(struct ipxhdr *packet, int length) { - /* - * NOTE: sum is a net byte order quantity, which optimizes the + /* + * NOTE: sum is a net byte order quantity, which optimizes the * loop. This only works on big and little endian machines. (I * don't know of a machine that isn't.) */ - /* start at ipx_dest - We skip the checksum field and start with - * ipx_type before the loop, not considering ipx_tctrl in the calc */ - __u16 *p = (__u16 *)&packet->ipx_dest; - __u32 i = (length >> 1) - 1; /* Number of complete words */ - __u32 sum = packet->ipx_type << sizeof(packet->ipx_tctrl); - - /* Loop through all complete words except the checksum field, - * ipx_type (accounted above) and ipx_tctrl (not used in the cksum) */ - while (--i) + /* handle the first 3 words separately; checksum should be skipped + * and ipx_tctrl masked out */ + __u16 *p = (__u16 *)packet; + __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff)); + __u32 i = (length >> 1) - 3; /* Number of remaining complete words */ + + /* Loop through them */ + p += 3; + while (i--) sum += *p++; /* Add on the last part word if it exists */ if (packet->ipx_pktsize & htons(1)) - sum += ntohs(0xff00) & *p; + sum += (__force u16)htons(0xff00) & *p; /* Do final fixup */ sum = (sum & 0xffff) + (sum >> 16); @@ -1263,7 +1256,14 @@ __u16 ipx_cksum(struct ipxhdr *packet, int length) if (sum >= 0x10000) sum++; - return ~sum; + /* + * Leave 0 alone; we don't want 0xffff here. Note that we can't get + * here with 0x10000, so this check is the same as ((__u16)sum) + */ + if (sum) + sum = ~sum; + + return (__force __be16)sum; } const char *ipx_frame_name(__be16 frame) @@ -1335,7 +1335,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname, rc = -EINVAL; if(len < 0) goto out; - + rc = -EFAULT; if (put_user(len, optlen) || copy_to_user(optval, &val, len)) goto out; @@ -1351,11 +1351,14 @@ static struct proto ipx_proto = { .obj_size = sizeof(struct ipx_sock), }; -static int ipx_create(struct socket *sock, int protocol) +static int ipx_create(struct net *net, struct socket *sock, int protocol) { int rc = -ESOCKTNOSUPPORT; struct sock *sk; + if (net != &init_net) + return -EAFNOSUPPORT; + /* * SPX support is not anymore in the kernel sources. If you want to * ressurrect it, completing it and making it understand shared skbs, @@ -1365,15 +1368,12 @@ static int ipx_create(struct socket *sock, int protocol) if (sock->type != SOCK_DGRAM) goto out; - rc = -ENOMEM; - sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1); + rc = -ENOMEM; + sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto); if (!sk) goto out; -#ifdef IPX_REFCNT_DEBUG - atomic_inc(&ipx_sock_nr); - printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk, - atomic_read(&ipx_sock_nr)); -#endif + + sk_refcnt_debug_inc(sk); sock_init_data(sock, sk); sk->sk_no_check = 1; /* Checksum off by default */ sock->ops = &ipx_dgram_ops; @@ -1394,6 +1394,7 @@ static int ipx_release(struct socket *sock) sock_set_flag(sk, SOCK_DEAD); sock->sk = NULL; + sk_refcnt_debug_release(sk); ipx_destroy_socket(sk); out: return 0; @@ -1554,7 +1555,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, goto out; } - /* We can either connect to primary network or somewhere + /* We can either connect to primary network or somewhere * we can route to */ rt = ipxrtr_lookup(addr->sipx_network); rc = -ENETUNREACH; @@ -1634,10 +1635,13 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty struct ipxhdr *ipx; u16 ipx_pktsize; int rc = 0; - - /* Not ours */ - if (skb->pkt_type == PACKET_OTHERHOST) - goto drop; + + if (!net_eq(dev_net(dev), &init_net)) + goto drop; + + /* Not ours */ + if (skb->pkt_type == PACKET_OTHERHOST) + goto drop; if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; @@ -1646,12 +1650,12 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty goto drop; ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); - + /* Too small or invalid header? */ if (ipx_pktsize < sizeof(struct ipxhdr) || !pskb_may_pull(skb, ipx_pktsize)) goto drop; - + ipx = ipx_hdr(skb); if (ipx->ipx_checksum != IPX_NO_CHECKSUM && ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) @@ -1779,7 +1783,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, if (rc) goto out; } - + rc = -ENOTCONN; if (sock_flag(sk, SOCK_ZAPPED)) goto out; @@ -1800,8 +1804,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, copied); if (rc) goto out_free; - if (skb->tstamp.off_sec) - skb_get_timestamp(skb, &sk->sk_stamp); + if (skb->tstamp.tv64) + sk->sk_stamp = skb->tstamp; msg->msg_namelen = sizeof(*sipx); @@ -1868,15 +1872,15 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) * This socket wants to take care of the NCP connection * handed to us in arg. */ - rc = -EPERM; - if (!capable(CAP_NET_ADMIN)) + rc = -EPERM; + if (!capable(CAP_NET_ADMIN)) break; rc = get_user(ipx_sk(sk)->ipx_ncp_conn, (const unsigned short __user *)argp); break; case SIOCGSTAMP: rc = -EINVAL; - if (sk) + if (sk) rc = sock_get_timestamp(sk, argp); break; case SIOCGIFDSTADDR: @@ -1952,16 +1956,15 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .sendpage = sock_no_sendpage, }; -#include SOCKOPS_WRAP(ipx_dgram, PF_IPX); -static struct packet_type ipx_8023_packet_type = { - .type = __constant_htons(ETH_P_802_3), +static struct packet_type ipx_8023_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_802_3), .func = ipx_rcv, }; -static struct packet_type ipx_dix_packet_type = { - .type = __constant_htons(ETH_P_IPX), +static struct packet_type ipx_dix_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_IPX), .func = ipx_rcv, }; @@ -1972,15 +1975,15 @@ static struct notifier_block ipx_dev_notifier = { extern struct datalink_proto *make_EII_client(void); extern void destroy_EII_client(struct datalink_proto *); -static unsigned char ipx_8022_type = 0xE0; -static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; -static char ipx_EII_err_msg[] __initdata = +static const unsigned char ipx_8022_type = 0xE0; +static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; +static const char ipx_EII_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with Ethernet II\n"; -static char ipx_8023_err_msg[] __initdata = +static const char ipx_8023_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with 802.3\n"; -static char ipx_llc_err_msg[] __initdata = +static const char ipx_llc_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with 802.2\n"; -static char ipx_snap_err_msg[] __initdata = +static const char ipx_snap_err_msg[] __initconst = KERN_CRIT "IPX: Unable to register with SNAP\n"; static int __init ipx_init(void) @@ -2028,19 +2031,27 @@ static void __exit ipx_proto_finito(void) ipxitf_cleanup(); - unregister_snap_client(pSNAP_datalink); - pSNAP_datalink = NULL; + if (pSNAP_datalink) { + unregister_snap_client(pSNAP_datalink); + pSNAP_datalink = NULL; + } - unregister_8022_client(p8022_datalink); - p8022_datalink = NULL; + if (p8022_datalink) { + unregister_8022_client(p8022_datalink); + p8022_datalink = NULL; + } dev_remove_pack(&ipx_8023_packet_type); - destroy_8023_client(p8023_datalink); - p8023_datalink = NULL; + if (p8023_datalink) { + destroy_8023_client(p8023_datalink); + p8023_datalink = NULL; + } dev_remove_pack(&ipx_dix_packet_type); - destroy_EII_client(pEII_datalink); - pEII_datalink = NULL; + if (pEII_datalink) { + destroy_EII_client(pEII_datalink); + pEII_datalink = NULL; + } proto_unregister(&ipx_proto); sock_unregister(ipx_family_ops.family);