diff options
Diffstat (limited to 'net/ax25/af_ax25.c')
| -rw-r--r-- | net/ax25/af_ax25.c | 223 |
1 files changed, 102 insertions, 121 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 48bfcc741f2..c35c3f48fc0 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -25,6 +25,7 @@ #include <linux/string.h> #include <linux/sockios.h> #include <linux/net.h> +#include <linux/slab.h> #include <net/ax25.h> #include <linux/inet.h> #include <linux/netdevice.h> @@ -32,7 +33,6 @@ #include <linux/skbuff.h> #include <net/sock.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <linux/fcntl.h> #include <linux/termios.h> /* For TIOCINQ/OUTQ */ #include <linux/mm.h> @@ -81,14 +81,13 @@ static void ax25_kill_by_device(struct net_device *dev) { ax25_dev *ax25_dev; ax25_cb *s; - struct hlist_node *node; if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) return; spin_lock_bh(&ax25_list_lock); again: - ax25_for_each(s, node, &ax25_list) { + ax25_for_each(s, &ax25_list) { if (s->ax25_dev == ax25_dev) { s->ax25_dev = NULL; spin_unlock_bh(&ax25_list_lock); @@ -112,11 +111,11 @@ again: * Handle device status changes. */ static int ax25_device_event(struct notifier_block *this, unsigned long event, - void *ptr) + void *ptr) { - struct net_device *dev = (struct net_device *)ptr; + struct net_device *dev = netdev_notifier_info_to_dev(ptr); - if (dev->nd_net != &init_net) + if (!net_eq(dev_net(dev), &init_net)) return NOTIFY_DONE; /* Reject non AX.25 devices */ @@ -158,10 +157,9 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device *dev, int type) { ax25_cb *s; - struct hlist_node *node; spin_lock(&ax25_list_lock); - ax25_for_each(s, node, &ax25_list) { + ax25_for_each(s, &ax25_list) { if ((s->iamdigi && !digi) || (!s->iamdigi && digi)) continue; if (s->sk && !ax25cmp(&s->source_addr, addr) && @@ -187,10 +185,9 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr, { struct sock *sk = NULL; ax25_cb *s; - struct hlist_node *node; spin_lock(&ax25_list_lock); - ax25_for_each(s, node, &ax25_list) { + ax25_for_each(s, &ax25_list) { if (s->sk && !ax25cmp(&s->source_addr, my_addr) && !ax25cmp(&s->dest_addr, dest_addr) && s->sk->sk_type == type) { @@ -213,10 +210,9 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi *digi, struct net_device *dev) { ax25_cb *s; - struct hlist_node *node; spin_lock_bh(&ax25_list_lock); - ax25_for_each(s, node, &ax25_list) { + ax25_for_each(s, &ax25_list) { if (s->sk && s->sk->sk_type != SOCK_SEQPACKET) continue; if (s->ax25_dev == NULL) @@ -248,10 +244,9 @@ void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto) { ax25_cb *s; struct sk_buff *copy; - struct hlist_node *node; spin_lock(&ax25_list_lock); - ax25_for_each(s, node, &ax25_list) { + ax25_for_each(s, &ax25_list) { if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->sk_type == SOCK_RAW && s->sk->sk_protocol == proto && @@ -317,6 +312,9 @@ void ax25_destroy_socket(ax25_cb *ax25) /* Queue the unaccepted socket for death */ sock_orphan(skb->sk); + /* 9A4GL: hack to release unaccepted sockets */ + skb->sk->sk_state = TCP_LISTEN; + ax25_start_heartbeat(sax25); sax25->state = AX25_STATE_0; } @@ -327,8 +325,7 @@ void ax25_destroy_socket(ax25_cb *ax25) } if (ax25->sk != NULL) { - if (atomic_read(&ax25->sk->sk_wmem_alloc) || - atomic_read(&ax25->sk->sk_rmem_alloc)) { + if (sk_has_allocations(ax25->sk)) { /* Defer: outstanding buffers */ setup_timer(&ax25->dtimer, ax25_destroy_timer, (unsigned long)ax25); @@ -356,6 +353,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg) ax25_dev *ax25_dev; ax25_cb *ax25; unsigned int k; + int ret = 0; if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl))) return -EFAULT; @@ -366,6 +364,9 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg) if (ax25_ctl.digi_count > AX25_MAX_DIGIS) return -EINVAL; + if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL) + return -EINVAL; + digi.ndigi = ax25_ctl.digi_count; for (k = 0; k < digi.ndigi; k++) digi.calls[k] = ax25_ctl.digi_addr[k]; @@ -386,57 +387,64 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg) case AX25_WINDOW: if (ax25->modulus == AX25_MODULUS) { if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7) - return -EINVAL; + goto einval_put; } else { if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63) - return -EINVAL; + goto einval_put; } ax25->window = ax25_ctl.arg; break; case AX25_T1: - if (ax25_ctl.arg < 1) - return -EINVAL; + if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ) + goto einval_put; ax25->rtt = (ax25_ctl.arg * HZ) / 2; ax25->t1 = ax25_ctl.arg * HZ; break; case AX25_T2: - if (ax25_ctl.arg < 1) - return -EINVAL; + if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ) + goto einval_put; ax25->t2 = ax25_ctl.arg * HZ; break; case AX25_N2: if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31) - return -EINVAL; + goto einval_put; ax25->n2count = 0; ax25->n2 = ax25_ctl.arg; break; case AX25_T3: - if (ax25_ctl.arg < 0) - return -EINVAL; + if (ax25_ctl.arg > ULONG_MAX / HZ) + goto einval_put; ax25->t3 = ax25_ctl.arg * HZ; break; case AX25_IDLE: - if (ax25_ctl.arg < 0) - return -EINVAL; + if (ax25_ctl.arg > ULONG_MAX / (60 * HZ)) + goto einval_put; + ax25->idle = ax25_ctl.arg * 60 * HZ; break; case AX25_PACLEN: if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535) - return -EINVAL; + goto einval_put; ax25->paclen = ax25_ctl.arg; break; default: - return -EINVAL; + goto einval_put; } - return 0; +out_put: + ax25_cb_put(ax25); + return ret; + +einval_put: + ret = -EINVAL; + goto out_put; } static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev) @@ -525,21 +533,22 @@ ax25_cb *ax25_create_cb(void) */ static int ax25_setsockopt(struct socket *sock, int level, int optname, - char __user *optval, int optlen) + char __user *optval, unsigned int optlen) { struct sock *sk = sock->sk; ax25_cb *ax25; struct net_device *dev; char devname[IFNAMSIZ]; - int opt, res = 0; + unsigned long opt; + int res = 0; if (level != SOL_AX25) return -ENOPROTOOPT; - if (optlen < sizeof(int)) + if (optlen < sizeof(unsigned int)) return -EINVAL; - if (get_user(opt, (int __user *)optval)) + if (get_user(opt, (unsigned int __user *)optval)) return -EFAULT; lock_sock(sk); @@ -562,7 +571,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, break; case AX25_T1: - if (opt < 1) { + if (opt < 1 || opt > ULONG_MAX / HZ) { res = -EINVAL; break; } @@ -571,7 +580,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, break; case AX25_T2: - if (opt < 1) { + if (opt < 1 || opt > ULONG_MAX / HZ) { res = -EINVAL; break; } @@ -587,7 +596,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, break; case AX25_T3: - if (opt < 1) { + if (opt < 1 || opt > ULONG_MAX / HZ) { res = -EINVAL; break; } @@ -595,7 +604,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, break; case AX25_IDLE: - if (opt < 0) { + if (opt > ULONG_MAX / (60 * HZ)) { res = -EINVAL; break; } @@ -603,7 +612,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, break; case AX25_BACKOFF: - if (opt < 0 || opt > 2) { + if (opt > 2) { res = -EINVAL; break; } @@ -632,15 +641,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, case SO_BINDTODEVICE: if (optlen > IFNAMSIZ) - optlen=IFNAMSIZ; - if (copy_from_user(devname, optval, optlen)) { - res = -EFAULT; - break; - } + optlen = IFNAMSIZ; - dev = dev_get_by_name(&init_net, devname); - if (dev == NULL) { - res = -ENODEV; + if (copy_from_user(devname, optval, optlen)) { + res = -EFAULT; break; } @@ -648,12 +652,18 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, (sock->state != SS_UNCONNECTED || sk->sk_state == TCP_LISTEN)) { res = -EADDRNOTAVAIL; - dev_put(dev); + break; + } + + dev = dev_get_by_name(&init_net, devname); + if (!dev) { + res = -ENODEV; break; } ax25->ax25_dev = ax25_dev_ax25dev(dev); ax25_fillin_cb(ax25, ax25->ax25_dev); + dev_put(dev); break; default: @@ -790,12 +800,13 @@ static struct proto ax25_proto = { .obj_size = sizeof(struct sock), }; -static int ax25_create(struct net *net, struct socket *sock, int protocol) +static int ax25_create(struct net *net, struct socket *sock, int protocol, + int kern) { struct sock *sk; ax25_cb *ax25; - if (net != &init_net) + if (!net_eq(net, &init_net)) return -EAFNOSUPPORT; switch (sock->type) { @@ -826,6 +837,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol) case AX25_P_NETROM: if (ax25_protocol_is_registered(AX25_P_NETROM)) return -ESOCKTNOSUPPORT; + break; #endif #ifdef CONFIG_ROSE_MODULE case AX25_P_ROSE: @@ -869,7 +881,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) struct sock *sk; ax25_cb *ax25, *oax25; - sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot); + sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC, osk->sk_prot); if (sk == NULL) return NULL; @@ -891,15 +903,12 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) sock_init_data(NULL, sk); - sk->sk_destruct = ax25_free_sock; sk->sk_type = osk->sk_type; - sk->sk_socket = osk->sk_socket; sk->sk_priority = osk->sk_priority; sk->sk_protocol = osk->sk_protocol; sk->sk_rcvbuf = osk->sk_rcvbuf; sk->sk_sndbuf = osk->sk_sndbuf; sk->sk_state = TCP_ESTABLISHED; - sk->sk_sleep = osk->sk_sleep; sock_copy_flags(sk, osk); oax25 = ax25_sk(osk); @@ -931,6 +940,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev) } sk->sk_protinfo = ax25; + sk->sk_destruct = ax25_free_sock; ax25->sk = sk; return sk; @@ -1044,7 +1054,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; - user = ax25_findbyuid(current->euid); + user = ax25_findbyuid(current_euid()); if (user) { call = user->call; ax25_uid_put(user); @@ -1094,7 +1104,7 @@ done: out: release_sock(sk); - return 0; + return err; } /* @@ -1272,7 +1282,7 @@ static int __must_check ax25_connect(struct socket *sock, DEFINE_WAIT(wait); for (;;) { - prepare_to_wait(sk->sk_sleep, &wait, + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); if (sk->sk_state != TCP_SYN_SENT) break; @@ -1285,7 +1295,7 @@ static int __must_check ax25_connect(struct socket *sock, err = -ERESTARTSYS; break; } - finish_wait(sk->sk_sleep, &wait); + finish_wait(sk_sleep(sk), &wait); if (err) goto out_release; @@ -1337,7 +1347,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) * hooked into the SABM we saved */ for (;;) { - prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE); + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); skb = skb_dequeue(&sk->sk_receive_queue); if (skb) break; @@ -1355,19 +1365,17 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) err = -ERESTARTSYS; break; } - finish_wait(sk->sk_sleep, &wait); + finish_wait(sk_sleep(sk), &wait); if (err) goto out; newsk = skb->sk; - newsk->sk_socket = newsock; - newsk->sk_sleep = &newsock->wait; + sock_graft(newsk, newsock); /* Now attach up the new socket */ kfree_skb(skb); sk->sk_ack_backlog--; - newsock->sk = newsk; newsock->state = SS_CONNECTED; out: @@ -1385,6 +1393,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, ax25_cb *ax25; int err = 0; + memset(fsa, 0, sizeof(*fsa)); lock_sock(sk); ax25 = ax25_sk(sk); @@ -1396,7 +1405,6 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, fsa->fsa_ax25.sax25_family = AF_AX25; fsa->fsa_ax25.sax25_call = ax25->dest_addr; - fsa->fsa_ax25.sax25_ndigis = 0; if (ax25->digipeat != NULL) { ndigi = ax25->digipeat->ndigi; @@ -1427,7 +1435,7 @@ out: static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) { - struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; + DECLARE_SOCKADDR(struct sockaddr_ax25 *, usax, msg->msg_name); struct sock *sk = sock->sk; struct sockaddr_ax25 sax; struct sk_buff *skb; @@ -1530,11 +1538,7 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, dp = ax25->digipeat; } - SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n"); - /* Build a packet */ - SOCK_DEBUG(sk, "AX.25: sendto: building packet.\n"); - /* Assume the worst case */ size = len + ax25->ax25_dev->dev->hard_header_len; @@ -1544,8 +1548,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, skb_reserve(skb, size - len); - SOCK_DEBUG(sk, "AX.25: Appending user data\n"); - /* User data follows immediately after the AX.25 data */ if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { err = -EFAULT; @@ -1559,8 +1561,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, if (!ax25->pidincl) *skb_push(skb, 1) = sk->sk_protocol; - SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n"); - if (sk->sk_type == SOCK_SEQPACKET) { /* Connected mode sockets go via the LAPB machine */ if (sk->sk_state != TCP_ESTABLISHED) { @@ -1578,22 +1578,14 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, skb_push(skb, 1 + ax25_addr_size(dp)); - SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp); - - if (dp != NULL) - SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi); + /* Building AX.25 Header */ /* Build an AX.25 header */ lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call, dp, AX25_COMMAND, AX25_MODULUS); - SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv); - skb_set_transport_header(skb, lv); - SOCK_DEBUG(sk, "base=%p pos=%p\n", - skb->data, skb_transport_header(skb)); - *skb_transport_header(skb) = AX25_UI; /* Datagram frames go straight out of the door as UI */ @@ -1644,12 +1636,13 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (msg->msg_namelen != 0) { - struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; + if (msg->msg_name) { ax25_digi digi; ax25_address src; const unsigned char *mac = skb_mac_header(skb); + DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name); + memset(sax, 0, sizeof(struct full_sockaddr_ax25)); ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, &digi, NULL, NULL); sax->sax25_family = AF_AX25; @@ -1694,7 +1687,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) switch (cmd) { case TIOCOUTQ: { long amount; - amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); + + amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); if (amount < 0) amount = 0; res = put_user(amount, (int __user *)argp); @@ -1741,7 +1735,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) res = -EFAULT; break; } - if (amount > AX25_NOUID_BLOCK) { + if (amount < 0 || amount > AX25_NOUID_BLOCK) { res = -EINVAL; break; } @@ -1784,8 +1778,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ); ax25_info.n2count = ax25->n2count; ax25_info.state = ax25->state; - ax25_info.rcv_q = atomic_read(&sk->sk_rmem_alloc); - ax25_info.snd_q = atomic_read(&sk->sk_wmem_alloc); + ax25_info.rcv_q = sk_rmem_alloc_get(sk); + ax25_info.snd_q = sk_wmem_alloc_get(sk); ax25_info.vs = ax25->vs; ax25_info.vr = ax25->vr; ax25_info.va = ax25->va; @@ -1858,25 +1852,13 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static void *ax25_info_start(struct seq_file *seq, loff_t *pos) __acquires(ax25_list_lock) { - struct ax25_cb *ax25; - struct hlist_node *node; - int i = 0; - spin_lock_bh(&ax25_list_lock); - ax25_for_each(ax25, node, &ax25_list) { - if (i == *pos) - return ax25; - ++i; - } - return NULL; + return seq_hlist_start(&ax25_list, *pos); } static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos) { - ++*pos; - - return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next, - struct ax25_cb, ax25_node); + return seq_hlist_next(v, &ax25_list, pos); } static void ax25_info_stop(struct seq_file *seq, void *v) @@ -1887,7 +1869,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v) static int ax25_info_show(struct seq_file *seq, void *v) { - ax25_cb *ax25 = v; + ax25_cb *ax25 = hlist_entry(v, struct ax25_cb, ax25_node); char buf[11]; int k; @@ -1925,8 +1907,8 @@ static int ax25_info_show(struct seq_file *seq, void *v) if (ax25->sk != NULL) { seq_printf(seq, " %d %d %lu\n", - atomic_read(&ax25->sk->sk_wmem_alloc), - atomic_read(&ax25->sk->sk_rmem_alloc), + sk_wmem_alloc_get(ax25->sk), + sk_rmem_alloc_get(ax25->sk), sock_i_ino(ax25->sk)); } else { seq_puts(seq, " * * *\n"); @@ -1956,7 +1938,7 @@ static const struct file_operations ax25_info_fops = { #endif -static struct net_proto_family ax25_family_ops = { +static const struct net_proto_family ax25_family_ops = { .family = PF_AX25, .create = ax25_create, .owner = THIS_MODULE, @@ -1986,14 +1968,13 @@ static const struct proto_ops ax25_proto_ops = { /* * Called by socket.c on kernel start up */ -static struct packet_type ax25_packet_type = { - .type = __constant_htons(ETH_P_AX25), - .dev = NULL, /* All devices */ +static struct packet_type ax25_packet_type __read_mostly = { + .type = cpu_to_be16(ETH_P_AX25), .func = ax25_kiss_rcv, }; static struct notifier_block ax25_dev_notifier = { - .notifier_call =ax25_device_event, + .notifier_call = ax25_device_event, }; static int __init ax25_init(void) @@ -2006,11 +1987,11 @@ static int __init ax25_init(void) sock_register(&ax25_family_ops); dev_add_pack(&ax25_packet_type); register_netdevice_notifier(&ax25_dev_notifier); - ax25_register_sysctl(); - proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops); - proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops); - proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops); + proc_create("ax25_route", S_IRUGO, init_net.proc_net, + &ax25_route_fops); + proc_create("ax25", S_IRUGO, init_net.proc_net, &ax25_info_fops); + proc_create("ax25_calls", S_IRUGO, init_net.proc_net, &ax25_uid_fops); out: return rc; } @@ -2024,19 +2005,19 @@ MODULE_ALIAS_NETPROTO(PF_AX25); static void __exit ax25_exit(void) { - proc_net_remove(&init_net, "ax25_route"); - proc_net_remove(&init_net, "ax25"); - proc_net_remove(&init_net, "ax25_calls"); - ax25_rt_free(); - ax25_uid_free(); - ax25_dev_free(); + remove_proc_entry("ax25_route", init_net.proc_net); + remove_proc_entry("ax25", init_net.proc_net); + remove_proc_entry("ax25_calls", init_net.proc_net); - ax25_unregister_sysctl(); unregister_netdevice_notifier(&ax25_dev_notifier); dev_remove_pack(&ax25_packet_type); sock_unregister(PF_AX25); proto_unregister(&ax25_proto); + + ax25_rt_free(); + ax25_uid_free(); + ax25_dev_free(); } module_exit(ax25_exit); |
