Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Phonet: implement GPRS virtual interface over PEP socket

Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Rémi Denis-Courmont and committed by
David S. Miller
02a47617 c41bd97f

+550 -16
+8
include/linux/phonet.h
··· 31 31 #define PN_PROTO_PIPE 2 32 32 #define PHONET_NPROTO 3 33 33 34 + /* Socket options for SOL_PNPIPE level */ 35 + #define PNPIPE_ENCAP 1 36 + #define PNPIPE_IFINDEX 2 37 + 34 38 #define PNADDR_ANY 0 35 39 #define PNPORT_RESOURCE_ROUTING 0 40 + 41 + /* Values for PNPIPE_ENCAP option */ 42 + #define PNPIPE_ENCAP_NONE 0 43 + #define PNPIPE_ENCAP_IP 1 36 44 37 45 /* ioctls */ 38 46 #define SIOCPNGETOBJECT (SIOCPROTOPRIVATE + 0)
+1
include/linux/socket.h
··· 297 297 #define SOL_RXRPC 272 298 298 #define SOL_PPPOL2TP 273 299 299 #define SOL_BLUETOOTH 274 300 + #define SOL_PNPIPE 275 300 301 301 302 /* IPX options */ 302 303 #define IPX_TYPE 1
+38
include/net/phonet/gprs.h
··· 1 + /* 2 + * File: pep_gprs.h 3 + * 4 + * GPRS over Phonet pipe end point socket 5 + * 6 + * Copyright (C) 2008 Nokia Corporation. 7 + * 8 + * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License 12 + * version 2 as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, but 15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 + * 02110-1301 USA 23 + */ 24 + 25 + #ifndef NET_PHONET_GPRS_H 26 + #define NET_PHONET_GPRS_H 27 + 28 + struct sock; 29 + struct sk_buff; 30 + 31 + int pep_writeable(struct sock *sk); 32 + int pep_write(struct sock *sk, struct sk_buff *skb); 33 + struct sk_buff *pep_read(struct sock *sk); 34 + 35 + int gprs_attach(struct sock *sk); 36 + void gprs_detach(struct sock *sk); 37 + 38 + #endif
+1
include/net/phonet/pep.h
··· 35 35 struct sock *listener; 36 36 struct sk_buff_head ctrlreq_queue; 37 37 #define PNPIPE_CTRLREQ_MAX 10 38 + int ifindex; 38 39 u16 peer_type; /* peer type/subtype */ 39 40 u8 pipe_handle; 40 41
+1 -1
net/phonet/Makefile
··· 8 8 sysctl.o \ 9 9 af_phonet.o 10 10 11 - pn_pep-objs := pep.o 11 + pn_pep-objs := pep.o pep-gprs.o
+347
net/phonet/pep-gprs.c
··· 1 + /* 2 + * File: pep-gprs.c 3 + * 4 + * GPRS over Phonet pipe end point socket 5 + * 6 + * Copyright (C) 2008 Nokia Corporation. 7 + * 8 + * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> 9 + * 10 + * This program is free software; you can redistribute it and/or 11 + * modify it under the terms of the GNU General Public License 12 + * version 2 as published by the Free Software Foundation. 13 + * 14 + * This program is distributed in the hope that it will be useful, but 15 + * WITHOUT ANY WARRANTY; without even the implied warranty of 16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 + * General Public License for more details. 18 + * 19 + * You should have received a copy of the GNU General Public License 20 + * along with this program; if not, write to the Free Software 21 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 + * 02110-1301 USA 23 + */ 24 + 25 + #include <linux/kernel.h> 26 + #include <linux/netdevice.h> 27 + #include <linux/if_ether.h> 28 + #include <linux/if_arp.h> 29 + #include <net/sock.h> 30 + 31 + #include <linux/if_phonet.h> 32 + #include <net/tcp_states.h> 33 + #include <net/phonet/gprs.h> 34 + 35 + #define GPRS_DEFAULT_MTU 1400 36 + 37 + struct gprs_dev { 38 + struct sock *sk; 39 + void (*old_state_change)(struct sock *); 40 + void (*old_data_ready)(struct sock *, int); 41 + void (*old_write_space)(struct sock *); 42 + 43 + struct net_device *net; 44 + struct net_device_stats stats; 45 + 46 + struct sk_buff_head tx_queue; 47 + struct work_struct tx_work; 48 + spinlock_t tx_lock; 49 + unsigned tx_max; 50 + }; 51 + 52 + static int gprs_type_trans(struct sk_buff *skb) 53 + { 54 + const u8 *pvfc; 55 + u8 buf; 56 + 57 + pvfc = skb_header_pointer(skb, 0, 1, &buf); 58 + if (!pvfc) 59 + return 0; 60 + /* Look at IP version field */ 61 + switch (*pvfc >> 4) { 62 + case 4: 63 + return htons(ETH_P_IP); 64 + case 6: 65 + return htons(ETH_P_IPV6); 66 + } 67 + return 0; 68 + } 69 + 70 + /* 71 + * Socket callbacks 72 + */ 73 + 74 + static void gprs_state_change(struct sock *sk) 75 + { 76 + struct gprs_dev *dev = sk->sk_user_data; 77 + 78 + if (sk->sk_state == TCP_CLOSE_WAIT) { 79 + netif_stop_queue(dev->net); 80 + netif_carrier_off(dev->net); 81 + } 82 + } 83 + 84 + static int gprs_recv(struct gprs_dev *dev, struct sk_buff *skb) 85 + { 86 + int err = 0; 87 + u16 protocol = gprs_type_trans(skb); 88 + 89 + if (!protocol) { 90 + err = -EINVAL; 91 + goto drop; 92 + } 93 + 94 + if (likely(skb_headroom(skb) & 3)) { 95 + struct sk_buff *rskb, *fs; 96 + int flen = 0; 97 + 98 + /* Phonet Pipe data header is misaligned (3 bytes), 99 + * so wrap the IP packet as a single fragment of an head-less 100 + * socket buffer. The network stack will pull what it needs, 101 + * but at least, the whole IP payload is not memcpy'd. */ 102 + rskb = netdev_alloc_skb(dev->net, 0); 103 + if (!rskb) { 104 + err = -ENOBUFS; 105 + goto drop; 106 + } 107 + skb_shinfo(rskb)->frag_list = skb; 108 + rskb->len += skb->len; 109 + rskb->data_len += rskb->len; 110 + rskb->truesize += rskb->len; 111 + 112 + /* Avoid nested fragments */ 113 + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) 114 + flen += fs->len; 115 + skb->next = skb_shinfo(skb)->frag_list; 116 + skb_shinfo(skb)->frag_list = NULL; 117 + skb->len -= flen; 118 + skb->data_len -= flen; 119 + skb->truesize -= flen; 120 + 121 + skb = rskb; 122 + } 123 + 124 + skb->protocol = protocol; 125 + skb_reset_mac_header(skb); 126 + skb->dev = dev->net; 127 + 128 + if (likely(dev->net->flags & IFF_UP)) { 129 + dev->stats.rx_packets++; 130 + dev->stats.rx_bytes += skb->len; 131 + netif_rx(skb); 132 + skb = NULL; 133 + } else 134 + err = -ENODEV; 135 + 136 + drop: 137 + if (skb) { 138 + dev_kfree_skb(skb); 139 + dev->stats.rx_dropped++; 140 + } 141 + return err; 142 + } 143 + 144 + static void gprs_data_ready(struct sock *sk, int len) 145 + { 146 + struct gprs_dev *dev = sk->sk_user_data; 147 + struct sk_buff *skb; 148 + 149 + while ((skb = pep_read(sk)) != NULL) { 150 + skb_orphan(skb); 151 + gprs_recv(dev, skb); 152 + } 153 + } 154 + 155 + static void gprs_write_space(struct sock *sk) 156 + { 157 + struct gprs_dev *dev = sk->sk_user_data; 158 + unsigned credits = pep_writeable(sk); 159 + 160 + spin_lock_bh(&dev->tx_lock); 161 + dev->tx_max = credits; 162 + if (credits > skb_queue_len(&dev->tx_queue)) 163 + netif_wake_queue(dev->net); 164 + spin_unlock_bh(&dev->tx_lock); 165 + } 166 + 167 + /* 168 + * Network device callbacks 169 + */ 170 + 171 + static int gprs_xmit(struct sk_buff *skb, struct net_device *net) 172 + { 173 + struct gprs_dev *dev = netdev_priv(net); 174 + 175 + switch (skb->protocol) { 176 + case htons(ETH_P_IP): 177 + case htons(ETH_P_IPV6): 178 + break; 179 + default: 180 + dev_kfree_skb(skb); 181 + return 0; 182 + } 183 + 184 + spin_lock(&dev->tx_lock); 185 + if (likely(skb_queue_len(&dev->tx_queue) < dev->tx_max)) { 186 + skb_queue_tail(&dev->tx_queue, skb); 187 + skb = NULL; 188 + } 189 + if (skb_queue_len(&dev->tx_queue) >= dev->tx_max) 190 + netif_stop_queue(net); 191 + spin_unlock(&dev->tx_lock); 192 + 193 + schedule_work(&dev->tx_work); 194 + if (unlikely(skb)) 195 + dev_kfree_skb(skb); 196 + return 0; 197 + } 198 + 199 + static void gprs_tx(struct work_struct *work) 200 + { 201 + struct gprs_dev *dev = container_of(work, struct gprs_dev, tx_work); 202 + struct sock *sk = dev->sk; 203 + struct sk_buff *skb; 204 + 205 + while ((skb = skb_dequeue(&dev->tx_queue)) != NULL) { 206 + int err; 207 + 208 + dev->stats.tx_bytes += skb->len; 209 + dev->stats.tx_packets++; 210 + 211 + skb_orphan(skb); 212 + skb_set_owner_w(skb, sk); 213 + 214 + lock_sock(sk); 215 + err = pep_write(sk, skb); 216 + if (err) { 217 + LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n", 218 + dev->net->name, err); 219 + dev->stats.tx_aborted_errors++; 220 + dev->stats.tx_errors++; 221 + } 222 + release_sock(sk); 223 + } 224 + 225 + lock_sock(sk); 226 + gprs_write_space(sk); 227 + release_sock(sk); 228 + } 229 + 230 + static int gprs_set_mtu(struct net_device *net, int new_mtu) 231 + { 232 + if ((new_mtu < 576) || (new_mtu > (PHONET_MAX_MTU - 11))) 233 + return -EINVAL; 234 + 235 + net->mtu = new_mtu; 236 + return 0; 237 + } 238 + 239 + static struct net_device_stats *gprs_get_stats(struct net_device *net) 240 + { 241 + struct gprs_dev *dev = netdev_priv(net); 242 + 243 + return &dev->stats; 244 + } 245 + 246 + static void gprs_setup(struct net_device *net) 247 + { 248 + net->features = NETIF_F_FRAGLIST; 249 + net->type = ARPHRD_NONE; 250 + net->flags = IFF_POINTOPOINT | IFF_NOARP; 251 + net->mtu = GPRS_DEFAULT_MTU; 252 + net->hard_header_len = 0; 253 + net->addr_len = 0; 254 + net->tx_queue_len = 10; 255 + 256 + net->destructor = free_netdev; 257 + net->hard_start_xmit = gprs_xmit; /* mandatory */ 258 + net->change_mtu = gprs_set_mtu; 259 + net->get_stats = gprs_get_stats; 260 + } 261 + 262 + /* 263 + * External interface 264 + */ 265 + 266 + /* 267 + * Attach a GPRS interface to a datagram socket. 268 + * Returns the interface index on success, negative error code on error. 269 + */ 270 + int gprs_attach(struct sock *sk) 271 + { 272 + static const char ifname[] = "gprs%d"; 273 + struct gprs_dev *dev; 274 + struct net_device *net; 275 + int err; 276 + 277 + if (unlikely(sk->sk_type == SOCK_STREAM)) 278 + return -EINVAL; /* need packet boundaries */ 279 + 280 + /* Create net device */ 281 + net = alloc_netdev(sizeof(*dev), ifname, gprs_setup); 282 + if (!net) 283 + return -ENOMEM; 284 + dev = netdev_priv(net); 285 + dev->net = net; 286 + dev->tx_max = 0; 287 + spin_lock_init(&dev->tx_lock); 288 + skb_queue_head_init(&dev->tx_queue); 289 + INIT_WORK(&dev->tx_work, gprs_tx); 290 + 291 + netif_stop_queue(net); 292 + err = register_netdev(net); 293 + if (err) { 294 + free_netdev(net); 295 + return err; 296 + } 297 + 298 + lock_sock(sk); 299 + if (unlikely(sk->sk_user_data)) { 300 + err = -EBUSY; 301 + goto out_rel; 302 + } 303 + if (unlikely((1 << sk->sk_state & (TCPF_CLOSE|TCPF_LISTEN)) || 304 + sock_flag(sk, SOCK_DEAD))) { 305 + err = -EINVAL; 306 + goto out_rel; 307 + } 308 + sk->sk_user_data = dev; 309 + dev->old_state_change = sk->sk_state_change; 310 + dev->old_data_ready = sk->sk_data_ready; 311 + dev->old_write_space = sk->sk_write_space; 312 + sk->sk_state_change = gprs_state_change; 313 + sk->sk_data_ready = gprs_data_ready; 314 + sk->sk_write_space = gprs_write_space; 315 + release_sock(sk); 316 + 317 + sock_hold(sk); 318 + dev->sk = sk; 319 + 320 + printk(KERN_DEBUG"%s: attached\n", net->name); 321 + gprs_write_space(sk); /* kick off TX */ 322 + return net->ifindex; 323 + 324 + out_rel: 325 + release_sock(sk); 326 + unregister_netdev(net); 327 + return err; 328 + } 329 + 330 + void gprs_detach(struct sock *sk) 331 + { 332 + struct gprs_dev *dev = sk->sk_user_data; 333 + struct net_device *net = dev->net; 334 + 335 + lock_sock(sk); 336 + sk->sk_user_data = NULL; 337 + sk->sk_state_change = dev->old_state_change; 338 + sk->sk_data_ready = dev->old_data_ready; 339 + sk->sk_write_space = dev->old_write_space; 340 + release_sock(sk); 341 + 342 + printk(KERN_DEBUG"%s: detached\n", net->name); 343 + unregister_netdev(net); 344 + flush_scheduled_work(); 345 + sock_put(sk); 346 + skb_queue_purge(&dev->tx_queue); 347 + }
+150 -11
net/phonet/pep.c
··· 31 31 #include <linux/phonet.h> 32 32 #include <net/phonet/phonet.h> 33 33 #include <net/phonet/pep.h> 34 + #include <net/phonet/gprs.h> 34 35 35 36 /* sk_state values: 36 37 * TCP_CLOSE sock not in use yet ··· 613 612 static void pep_sock_close(struct sock *sk, long timeout) 614 613 { 615 614 struct pep_sock *pn = pep_sk(sk); 615 + int ifindex = 0; 616 616 617 617 sk_common_release(sk); 618 618 ··· 627 625 sk_del_node_init(sknode); 628 626 sk->sk_state = TCP_CLOSE; 629 627 } 628 + ifindex = pn->ifindex; 629 + pn->ifindex = 0; 630 630 release_sock(sk); 631 + 632 + if (ifindex) 633 + gprs_detach(sk); 631 634 } 632 635 633 636 static int pep_wait_connreq(struct sock *sk, int noblock) ··· 737 730 return 0; 738 731 } 739 732 733 + static int pep_setsockopt(struct sock *sk, int level, int optname, 734 + char __user *optval, int optlen) 735 + { 736 + struct pep_sock *pn = pep_sk(sk); 737 + int val = 0, err = 0; 738 + 739 + if (level != SOL_PNPIPE) 740 + return -ENOPROTOOPT; 741 + if (optlen >= sizeof(int)) { 742 + if (get_user(val, (int __user *) optval)) 743 + return -EFAULT; 744 + } 745 + 746 + lock_sock(sk); 747 + switch (optname) { 748 + case PNPIPE_ENCAP: 749 + if (val && val != PNPIPE_ENCAP_IP) { 750 + err = -EINVAL; 751 + break; 752 + } 753 + if (!pn->ifindex == !val) 754 + break; /* Nothing to do! */ 755 + if (!capable(CAP_NET_ADMIN)) { 756 + err = -EPERM; 757 + break; 758 + } 759 + if (val) { 760 + release_sock(sk); 761 + err = gprs_attach(sk); 762 + if (err > 0) { 763 + pn->ifindex = err; 764 + err = 0; 765 + } 766 + } else { 767 + pn->ifindex = 0; 768 + release_sock(sk); 769 + gprs_detach(sk); 770 + err = 0; 771 + } 772 + goto out_norel; 773 + default: 774 + err = -ENOPROTOOPT; 775 + } 776 + release_sock(sk); 777 + 778 + out_norel: 779 + return err; 780 + } 781 + 782 + static int pep_getsockopt(struct sock *sk, int level, int optname, 783 + char __user *optval, int __user *optlen) 784 + { 785 + struct pep_sock *pn = pep_sk(sk); 786 + int len, val; 787 + 788 + if (level != SOL_PNPIPE) 789 + return -ENOPROTOOPT; 790 + if (get_user(len, optlen)) 791 + return -EFAULT; 792 + 793 + switch (optname) { 794 + case PNPIPE_ENCAP: 795 + val = pn->ifindex ? PNPIPE_ENCAP_IP : PNPIPE_ENCAP_NONE; 796 + break; 797 + case PNPIPE_IFINDEX: 798 + val = pn->ifindex; 799 + break; 800 + default: 801 + return -ENOPROTOOPT; 802 + } 803 + 804 + len = min_t(unsigned int, sizeof(int), len); 805 + if (put_user(len, optlen)) 806 + return -EFAULT; 807 + if (put_user(val, (int __user *) optval)) 808 + return -EFAULT; 809 + return 0; 810 + } 811 + 812 + static int pipe_skb_send(struct sock *sk, struct sk_buff *skb) 813 + { 814 + struct pep_sock *pn = pep_sk(sk); 815 + struct pnpipehdr *ph; 816 + 817 + skb_push(skb, 3); 818 + skb_reset_transport_header(skb); 819 + ph = pnp_hdr(skb); 820 + ph->utid = 0; 821 + ph->message_id = PNS_PIPE_DATA; 822 + ph->pipe_handle = pn->pipe_handle; 823 + if (pn_flow_safe(pn->tx_fc) && pn->tx_credits) 824 + pn->tx_credits--; 825 + 826 + return pn_skb_send(sk, skb, &pipe_srv); 827 + } 828 + 740 829 static int pep_sendmsg(struct kiocb *iocb, struct sock *sk, 741 830 struct msghdr *msg, size_t len) 742 831 { 743 832 struct pep_sock *pn = pep_sk(sk); 744 833 struct sk_buff *skb = NULL; 745 - struct pnpipehdr *ph; 746 834 long timeo; 747 835 int flags = msg->msg_flags; 748 836 int err, done; ··· 903 801 if (err < 0) 904 802 goto out; 905 803 906 - __skb_push(skb, 3); 907 - skb_reset_transport_header(skb); 908 - ph = pnp_hdr(skb); 909 - ph->utid = 0; 910 - ph->message_id = PNS_PIPE_DATA; 911 - ph->pipe_handle = pn->pipe_handle; 912 - if (pn_flow_safe(pn->tx_fc)) /* credit-based flow control */ 913 - pn->tx_credits--; 914 - 915 - err = pn_skb_send(sk, skb, &pipe_srv); 804 + err = pipe_skb_send(sk, skb); 916 805 if (err >= 0) 917 806 err = len; /* success! */ 918 807 skb = NULL; ··· 911 818 release_sock(sk); 912 819 kfree_skb(skb); 913 820 return err; 821 + } 822 + 823 + int pep_writeable(struct sock *sk) 824 + { 825 + struct pep_sock *pn = pep_sk(sk); 826 + 827 + return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0; 828 + } 829 + 830 + int pep_write(struct sock *sk, struct sk_buff *skb) 831 + { 832 + struct sk_buff *rskb, *fs; 833 + int flen = 0; 834 + 835 + rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC); 836 + if (!rskb) { 837 + kfree_skb(skb); 838 + return -ENOMEM; 839 + } 840 + skb_shinfo(rskb)->frag_list = skb; 841 + rskb->len += skb->len; 842 + rskb->data_len += rskb->len; 843 + rskb->truesize += rskb->len; 844 + 845 + /* Avoid nested fragments */ 846 + for (fs = skb_shinfo(skb)->frag_list; fs; fs = fs->next) 847 + flen += fs->len; 848 + skb->next = skb_shinfo(skb)->frag_list; 849 + skb_shinfo(skb)->frag_list = NULL; 850 + skb->len -= flen; 851 + skb->data_len -= flen; 852 + skb->truesize -= flen; 853 + 854 + skb_reserve(rskb, MAX_PHONET_HEADER + 3); 855 + return pipe_skb_send(sk, rskb); 856 + } 857 + 858 + struct sk_buff *pep_read(struct sock *sk) 859 + { 860 + struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); 861 + 862 + if (sk->sk_state == TCP_ESTABLISHED) 863 + pipe_grant_credits(sk); 864 + return skb; 914 865 } 915 866 916 867 static int pep_recvmsg(struct kiocb *iocb, struct sock *sk, ··· 1039 902 .accept = pep_sock_accept, 1040 903 .ioctl = pep_ioctl, 1041 904 .init = pep_init, 905 + .setsockopt = pep_setsockopt, 906 + .getsockopt = pep_getsockopt, 1042 907 .sendmsg = pep_sendmsg, 1043 908 .recvmsg = pep_recvmsg, 1044 909 .backlog_rcv = pep_do_rcv,
+4 -4
net/phonet/socket.c
··· 342 342 .ioctl = pn_socket_ioctl, 343 343 .listen = pn_socket_listen, 344 344 .shutdown = sock_no_shutdown, 345 - .setsockopt = sock_no_setsockopt, 346 - .getsockopt = sock_no_getsockopt, 345 + .setsockopt = sock_common_setsockopt, 346 + .getsockopt = sock_common_getsockopt, 347 347 #ifdef CONFIG_COMPAT 348 - .compat_setsockopt = sock_no_setsockopt, 349 - .compat_getsockopt = compat_sock_no_getsockopt, 348 + .compat_setsockopt = compat_sock_common_setsockopt, 349 + .compat_getsockopt = compat_sock_common_getsockopt, 350 350 #endif 351 351 .sendmsg = pn_socket_sendmsg, 352 352 .recvmsg = sock_common_recvmsg,