X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fappletalk%2Fddp.c;h=7b1eb9a4fc96881a68f9c23e92ea1679edc8cb4d;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=123d928183b87b1e986e683dc1d5de5955889c0f;hpb=6a77f38946aaee1cd85eeec6cf4229b204c15071;p=linux-2.6.git diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 123d92818..7b1eb9a4f 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -52,18 +52,19 @@ */ #include +#include #include -#include #include #include /* For TIOCOUTQ/INQ */ #include #include #include +#include #include #include struct datalink_proto *ddp_dl, *aarp_dl; -static struct proto_ops atalk_dgram_ops; +static const struct proto_ops atalk_dgram_ops; /**************************************************************************\ * * @@ -100,8 +101,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to, continue; if (to->sat_addr.s_net == ATADDR_ANYNET && - to->sat_addr.s_node == ATADDR_BCAST && - at->src_net == atif->address.s_net) + to->sat_addr.s_node == ATADDR_BCAST) goto found; if (to->sat_addr.s_net == at->src_net && @@ -401,7 +401,7 @@ out_err: } /* Find a match for a specific network:node pair */ -static struct atalk_iface *atalk_find_interface(int net, int node) +static struct atalk_iface *atalk_find_interface(__be16 net, int node) { struct atalk_iface *iface; @@ -573,6 +573,7 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint) /* Fill in the routing entry */ rt->target = ta->sat_addr; + dev_hold(devhint); rt->dev = devhint; rt->flags = r->rt_flags; rt->gateway = ga->sat_addr; @@ -1015,6 +1016,12 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len) return sum ? htons((unsigned short)sum) : 0xFFFF; } +static struct proto ddp_proto = { + .name = "DDP", + .owner = THIS_MODULE, + .obj_size = sizeof(struct atalk_sock), +}; + /* * Create a socket. Initialise the socket, blank the addresses * set the state. @@ -1022,7 +1029,6 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len) static int atalk_create(struct socket *sock, int protocol) { struct sock *sk; - struct atalk_sock *at; int rc = -ESOCKTNOSUPPORT; /* @@ -1032,25 +1038,17 @@ static int atalk_create(struct socket *sock, int protocol) if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) goto out; rc = -ENOMEM; - sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1, NULL); + sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, &ddp_proto, 1); if (!sk) goto out; - at = sk->sk_protinfo = kmalloc(sizeof(*at), GFP_KERNEL); - if (!at) - goto outsk; - memset(at, 0, sizeof(*at)); rc = 0; sock->ops = &atalk_dgram_ops; sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); /* Checksums on by default */ - sk->sk_zapped = 1; + sock_set_flag(sk, SOCK_ZAPPED); out: return rc; -outsk: - sk_free(sk); - goto out; } /* Free a socket. No work needed */ @@ -1127,7 +1125,7 @@ static int atalk_autobind(struct sock *sk) n = atalk_pick_and_bind_port(sk, &sat); if (!n) - sk->sk_zapped = 0; + sock_reset_flag(sk, SOCK_ZAPPED); out: return n; } @@ -1139,7 +1137,8 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); - if (!sk->sk_zapped || addr_len != sizeof(struct sockaddr_at)) + if (!sock_flag(sk, SOCK_ZAPPED) || + addr_len != sizeof(struct sockaddr_at)) return -EINVAL; if (addr->sat_family != AF_APPLETALK) @@ -1174,7 +1173,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EADDRINUSE; } - sk->sk_zapped = 0; + sock_reset_flag(sk, SOCK_ZAPPED); return 0; } @@ -1209,7 +1208,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, #endif } - if (sk->sk_zapped) + if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) return -EBUSY; @@ -1236,7 +1235,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct atalk_sock *at = at_sk(sk); - if (sk->sk_zapped) + if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) return -ENOBUFS; @@ -1391,7 +1390,7 @@ free_it: * [ie ARPHRD_ETHERTALK] */ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt) + struct packet_type *pt, struct net_device *orig_dev) { struct ddpehdr *ddp; struct sock *sock; @@ -1444,8 +1443,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, else atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); - /* Not ours, so we route the packet via the correct AppleTalk iface */ if (!atif) { + /* Not ours, so we route the packet via the correct + * AppleTalk iface + */ atalk_route_packet(skb, dev, ddp, &ddphv, origlen); goto out; } @@ -1483,7 +1484,7 @@ freeit: * header and append a long one. */ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt) + struct packet_type *pt, struct net_device *orig_dev) { /* Expand any short form frames */ if (skb->mac.raw[2] == 1) { @@ -1529,7 +1530,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, } skb->h.raw = skb->data; - return atalk_rcv(skb, dev, pt); + return atalk_rcv(skb, dev, pt, orig_dev); freeit: kfree_skb(skb); return 0; @@ -1558,7 +1559,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr return -EMSGSIZE; if (usat) { - if (sk->sk_zapped) + if (sock_flag(sk, SOCK_ZAPPED)) if (atalk_autobind(sk) < 0) return -EBUSY; @@ -1593,9 +1594,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } else { struct atalk_addr at_hint; @@ -1604,11 +1602,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); - if (!rt) - return -ENETUNREACH; - dev = rt->dev; } + if (!rt) + return -ENETUNREACH; + + dev = rt->dev; SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); @@ -1678,6 +1677,20 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); /* loop back */ skb_orphan(skb); + if (ddp->deh_dnode == ATADDR_BCAST) { + struct atalk_addr at_lo; + + at_lo.s_node = 0; + at_lo.s_net = 0; + + rt = atrtr_find(&at_lo); + if (!rt) { + kfree_skb(skb); + return -ENETUNREACH; + } + dev = rt->dev; + skb->dev = dev; + } ddp_dl->request(ddp_dl, skb, dev->dev_addr); } else { SOCK_DEBUG(sk, "SK %p: send out.\n", sk); @@ -1751,7 +1764,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr */ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { - int rc = -EINVAL; + int rc = -ENOIOCTLCMD; struct sock *sk = sock->sk; void __user *argp = (void __user *)arg; @@ -1801,35 +1814,34 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = atif_ioctl(cmd, argp); rtnl_unlock(); break; - /* Physical layer ioctl calls */ - case SIOCSIFLINK: - case SIOCGIFHWADDR: - case SIOCSIFHWADDR: - case SIOCGIFFLAGS: - case SIOCSIFFLAGS: - case SIOCGIFTXQLEN: - case SIOCSIFTXQLEN: - case SIOCGIFMTU: - case SIOCGIFCONF: - case SIOCADDMULTI: - case SIOCDELMULTI: - case SIOCGIFCOUNT: - case SIOCGIFINDEX: - case SIOCGIFNAME: - rc = dev_ioctl(cmd, argp); - break; } return rc; } + +#ifdef CONFIG_COMPAT +static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + /* + * All Appletalk ioctls except SIOCATALKDIFADDR are standard. And + * SIOCATALKDIFADDR is handled by upper layer as well, so there is + * nothing to do. Eventually SIOCATALKDIFADDR should be moved + * here so there is no generic SIOCPROTOPRIVATE translation in the + * system. + */ + return -ENOIOCTLCMD; +} +#endif + + static struct net_proto_family atalk_family_ops = { .family = PF_APPLETALK, .create = atalk_create, .owner = THIS_MODULE, }; -static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { +static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { .family = PF_APPLETALK, .owner = THIS_MODULE, .release = atalk_release, @@ -1840,6 +1852,9 @@ static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = { .getname = atalk_getname, .poll = datagram_poll, .ioctl = atalk_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = atalk_compat_ioctl, +#endif .listen = sock_no_listen, .shutdown = sock_no_shutdown, .setsockopt = sock_no_setsockopt, @@ -1880,6 +1895,11 @@ static char atalk_err_snap[] __initdata = /* Called by proto.c on kernel start up */ static int __init atalk_init(void) { + int rc = proto_register(&ddp_proto, 0); + + if (rc != 0) + goto out; + (void)sock_register(&atalk_family_ops); ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); if (!ddp_dl) @@ -1892,7 +1912,8 @@ static int __init atalk_init(void) aarp_proto_init(); atalk_proc_init(); atalk_register_sysctl(); - return 0; +out: + return rc; } module_init(atalk_init); @@ -1917,6 +1938,7 @@ static void __exit atalk_exit(void) dev_remove_pack(&ppptalk_packet_type); unregister_snap_client(ddp_dl); sock_unregister(PF_APPLETALK); + proto_unregister(&ddp_proto); } module_exit(atalk_exit);