X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipx%2Faf_ipx.c;h=e6a50e82603b9290599295e4f9b6421229119af6;hb=4e76c8a9fa413ccc09d3f7f664183dcce3555d57;hp=163223daf47b77a67a17ac47fe71e462b5503e03;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 163223daf..e6a50e826 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -29,6 +29,7 @@ */ #include +#include #include #include #include @@ -44,7 +45,6 @@ #include #include #include -#include #include #include @@ -52,6 +52,7 @@ #include #include #include +#include #include @@ -75,10 +76,10 @@ static struct datalink_proto *pEII_datalink; static struct datalink_proto *p8023_datalink; static struct datalink_proto *pSNAP_datalink; -static struct proto_ops ipx_dgram_ops; +static const struct proto_ops ipx_dgram_ops; LIST_HEAD(ipx_interfaces); -spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(ipx_interfaces_lock); struct ipx_interface *ipx_primary_net; struct ipx_interface *ipx_internal_net; @@ -277,7 +278,7 @@ static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc, spin_lock_bh(&intrfc->if_sklist_lock); sk_for_each(s, node, &intrfc->if_sklist) { - struct ipx_opt *ipxs = ipx_sk(s); + struct ipx_sock *ipxs = ipx_sk(s); if (ipxs->port == port && !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN)) @@ -291,7 +292,7 @@ found: } #endif -void __ipxitf_down(struct ipx_interface *intrfc) +static void __ipxitf_down(struct ipx_interface *intrfc) { struct sock *s; struct hlist_node *node, *t; @@ -302,13 +303,13 @@ void __ipxitf_down(struct ipx_interface *intrfc) spin_lock_bh(&intrfc->if_sklist_lock); /* error sockets */ sk_for_each_safe(s, node, t, &intrfc->if_sklist) { - struct ipx_opt *ipxs = ipx_sk(s); + struct ipx_sock *ipxs = ipx_sk(s); s->sk_err = ENOLINK; s->sk_error_report(s); ipxs->intrfc = NULL; ipxs->port = 0; - s->sk_zapped = 1; /* Indicates it is no longer bound */ + sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */ sk_del_node_init(s); } INIT_HLIST_HEAD(&intrfc->if_sklist); @@ -335,6 +336,12 @@ void ipxitf_down(struct ipx_interface *intrfc) spin_unlock_bh(&ipx_interfaces_lock); } +static __inline__ void __ipxitf_put(struct ipx_interface *intrfc) +{ + if (atomic_dec_and_test(&intrfc->refcnt)) + __ipxitf_down(intrfc); +} + static int ipxitf_device_event(struct notifier_block *notifier, unsigned long event, void *ptr) { @@ -394,7 +401,7 @@ static int ipxitf_demux_socket(struct ipx_interface *intrfc, spin_lock_bh(&intrfc->if_sklist_lock); sk_for_each(s, node, &intrfc->if_sklist) { - struct ipx_opt *ipxs = ipx_sk(s); + struct ipx_sock *ipxs = ipx_sk(s); if (ipxs->port == ipx->ipx_dest.sock && (is_broadcast || !memcmp(ipx->ipx_dest.node, @@ -937,9 +944,9 @@ out: return rc; } -static int ipx_map_frame_type(unsigned char type) +static __be16 ipx_map_frame_type(unsigned char type) { - int rc = 0; + __be16 rc = 0; switch (type) { case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX); break; @@ -1339,49 +1346,41 @@ out: return rc; } +static struct proto ipx_proto = { + .name = "IPX", + .owner = THIS_MODULE, + .obj_size = sizeof(struct ipx_sock), +}; + static int ipx_create(struct socket *sock, int protocol) { int rc = -ESOCKTNOSUPPORT; - struct ipx_opt *ipx = NULL; struct sock *sk; - switch (sock->type) { - case SOCK_DGRAM: - sk = sk_alloc(PF_IPX, GFP_KERNEL, 1, NULL); - rc = -ENOMEM; - if (!sk) - goto out; - ipx = sk->sk_protinfo = kmalloc(sizeof(*ipx), GFP_KERNEL); - if (!ipx) - goto outsk; - memset(ipx, 0, sizeof(*ipx)); - sock->ops = &ipx_dgram_ops; - break; - case SOCK_SEQPACKET: - /* - * SPX support is not anymore in the kernel sources. If - * you want to ressurrect it, completing it and making - * it understand shared skbs, be fully multithreaded, - * etc, grab the sources in an early 2.5 kernel tree. - */ - case SOCK_STREAM: /* Allow higher levels to piggyback */ - default: + /* + * SPX support is not anymore in the kernel sources. If you want to + * ressurrect it, completing it and making it understand shared skbs, + * be fully multithreaded, etc, grab the sources in an early 2.5 kernel + * tree. + */ + if (sock->type != SOCK_DGRAM) + goto out; + + rc = -ENOMEM; + sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1); + 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 sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); sk->sk_no_check = 1; /* Checksum off by default */ + sock->ops = &ipx_dgram_ops; rc = 0; out: return rc; -outsk: - sk_free(sk); - goto out; } static int ipx_release(struct socket *sock) @@ -1427,12 +1426,12 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc) static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sock *sk = sock->sk; - struct ipx_opt *ipxs = ipx_sk(sk); + struct ipx_sock *ipxs = ipx_sk(sk); struct ipx_interface *intrfc; struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr; int rc = -EINVAL; - if (!sk->sk_zapped || addr_len != sizeof(struct sockaddr_ipx)) + if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx)) goto out; intrfc = ipxitf_find_using_net(addr->sipx_network); @@ -1510,7 +1509,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) #endif /* CONFIG_IPX_INTERN */ ipxitf_insert_socket(intrfc, sk); - sk->sk_zapped = 0; + sock_reset_flag(sk, SOCK_ZAPPED); rc = 0; out_put: @@ -1523,7 +1522,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { struct sock *sk = sock->sk; - struct ipx_opt *ipxs = ipx_sk(sk); + struct ipx_sock *ipxs = ipx_sk(sk); struct sockaddr_ipx *addr; int rc = -EINVAL; struct ipx_route *rt; @@ -1587,7 +1586,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, struct ipx_address *addr; struct sockaddr_ipx sipx; struct sock *sk = sock->sk; - struct ipx_opt *ipxs = ipx_sk(sk); + struct ipx_sock *ipxs = ipx_sk(sk); int rc; *uaddr_len = sizeof(struct sockaddr_ipx); @@ -1621,6 +1620,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr, sipx.sipx_family = AF_IPX; sipx.sipx_type = ipxs->type; + sipx.sipx_zero = 0; memcpy(uaddr, &sipx, sizeof(sipx)); rc = 0; @@ -1628,7 +1628,7 @@ out: return rc; } -int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) +static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { /* NULL here for pt means the packet was looped back */ struct ipx_interface *intrfc; @@ -1647,7 +1647,8 @@ int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) ipx_pktsize = ntohs(ipx->ipx_pktsize); /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len) + if (ipx_pktsize < sizeof(struct ipxhdr) + || !pskb_may_pull(skb, ipx_pktsize)) goto drop; if (ipx->ipx_checksum != IPX_NO_CHECKSUM && @@ -1686,7 +1687,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { struct sock *sk = sock->sk; - struct ipx_opt *ipxs = ipx_sk(sk); + struct ipx_sock *ipxs = ipx_sk(sk); struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name; struct sockaddr_ipx local_sipx; int rc = -EINVAL; @@ -1751,7 +1752,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; - struct ipx_opt *ipxs = ipx_sk(sk); + struct ipx_sock *ipxs = ipx_sk(sk); struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name; struct ipxhdr *ipx = NULL; struct sk_buff *skb; @@ -1778,7 +1779,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, } rc = -ENOTCONN; - if (sk->sk_zapped) + if (sock_flag(sk, SOCK_ZAPPED)) goto out; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, @@ -1797,8 +1798,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, copied); if (rc) goto out_free; - if (skb->stamp.tv_sec) - sk->sk_stamp = skb->stamp; + if (skb->tstamp.off_sec) + skb_get_timestamp(skb, &sk->sk_stamp); msg->msg_namelen = sizeof(*sipx); @@ -1808,6 +1809,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN); sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; sipx->sipx_type = ipx->ipx_type; + sipx->sipx_zero = 0; } rc = copied; @@ -1884,13 +1886,36 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = -EINVAL; break; default: - rc = dev_ioctl(cmd, argp); + rc = -ENOIOCTLCMD; break; } return rc; } + +#ifdef CONFIG_COMPAT +static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + /* + * These 4 commands use same structure on 32bit and 64bit. Rest of IPX + * commands is handled by generic ioctl code. As these commands are + * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic + * code. + */ + switch (cmd) { + case SIOCAIPXITFCRT: + case SIOCAIPXPRISLT: + case SIOCIPXCFGDATA: + case SIOCIPXNCPCONN: + return ipx_ioctl(sock, cmd, arg); + default: + return -ENOIOCTLCMD; + } +} +#endif + + /* * Socket family declarations */ @@ -1901,7 +1926,7 @@ static struct net_proto_family ipx_family_ops = { .owner = THIS_MODULE, }; -static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { +static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .family = PF_IPX, .owner = THIS_MODULE, .release = ipx_release, @@ -1912,6 +1937,9 @@ static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .getname = ipx_getname, .poll = datagram_poll, .ioctl = ipx_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ipx_compat_ioctl, +#endif .listen = sock_no_listen, .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ .setsockopt = ipx_setsockopt, @@ -1940,9 +1968,7 @@ static struct notifier_block ipx_dev_notifier = { }; extern struct datalink_proto *make_EII_client(void); -extern struct datalink_proto *make_8023_client(void); extern void destroy_EII_client(struct datalink_proto *); -extern void destroy_8023_client(struct datalink_proto *); static unsigned char ipx_8022_type = 0xE0; static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 }; @@ -1957,6 +1983,11 @@ static char ipx_snap_err_msg[] __initdata = static int __init ipx_init(void) { + int rc = proto_register(&ipx_proto, 1); + + if (rc != 0) + goto out; + sock_register(&ipx_family_ops); pEII_datalink = make_EII_client(); @@ -1982,7 +2013,8 @@ static int __init ipx_init(void) register_netdevice_notifier(&ipx_dev_notifier); ipx_register_sysctl(); ipx_proc_init(); - return 0; +out: + return rc; } static void __exit ipx_proto_finito(void) @@ -2008,6 +2040,7 @@ static void __exit ipx_proto_finito(void) destroy_EII_client(pEII_datalink); pEII_datalink = NULL; + proto_unregister(&ipx_proto); sock_unregister(ipx_family_ops.family); }