summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/phonet.txt32
-rw-r--r--include/linux/Kbuild2
-rw-r--r--include/linux/if_phonet.h11
-rw-r--r--net/phonet/pn_netlink.c91
4 files changed, 64 insertions, 72 deletions
diff --git a/Documentation/networking/phonet.txt b/Documentation/networking/phonet.txt
index f3c72e0..57d3e59 100644
--- a/Documentation/networking/phonet.txt
+++ b/Documentation/networking/phonet.txt
@@ -21,7 +21,7 @@ depending on the device, such as:
Packets format
--------------
-Phonet packet have a common header as follow:
+Phonet packets have a common header as follows:
struct phonethdr {
uint8_t pn_media; /* Media type (link-layer identifier) */
@@ -33,14 +33,17 @@ Phonet packet have a common header as follow:
uint8_t pn_sobj; /* Sender object ID */
};
-The device ID is split: the 6 higher order bits consitutes the device
-address, while the 2 lower order bits are used for multiplexing, as are
-the 8-bits object identifiers. As such, Phonet can be considered as a
+On Linux, the link-layer header includes the pn_media byte (see below).
+The next 7 bytes are part of the network-layer header.
+
+The device ID is split: the 6 higher-order bits consitute the device
+address, while the 2 lower-order bits are used for multiplexing, as are
+the 8-bit object identifiers. As such, Phonet can be considered as a
network layer with 6 bits of address space and 10 bits for transport
protocol (much like port numbers in IP world).
-The modem always has address number zero. Each other device has a its
-own 6-bits address.
+The modem always has address number zero. All other device have a their
+own 6-bit address.
Link layer
@@ -49,11 +52,18 @@ Link layer
Phonet links are always point-to-point links. The link layer header
consists of a single Phonet media type byte. It uniquely identifies the
link through which the packet is transmitted, from the modem's
-perspective.
-
-Linux Phonet network interfaces use a dedicated link layer type
-(ETH_P_PHONET) which is out of the Ethernet type range. They can only
-send and receive Phonet packets.
+perspective. Each Phonet network device shall prepend and set the media
+type byte as appropriate. For convenience, a common phonet_header_ops
+link-layer header operations structure is provided. It sets the
+media type according to the network device hardware address.
+
+Linux Phonet network interfaces support a dedicated link layer packets
+type (ETH_P_PHONET) which is out of the Ethernet type range. They can
+only send and receive Phonet packets.
+
+The virtual TUN tunnel device driver can also be used for Phonet. This
+requires IFF_TUN mode, _without_ the IFF_NO_PI flag. In this case,
+there is no link-layer header, so there is no Phonet media type byte.
Note that Phonet interfaces are not allowed to re-order packets, so
only the (default) Linux FIFO qdisc should be used with them.
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index b68ec09..f431e40 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -126,6 +126,7 @@ header-y += pci_regs.h
header-y += pfkeyv2.h
header-y += pg.h
header-y += phantom.h
+header-y += phonet.h
header-y += pkt_cls.h
header-y += pkt_sched.h
header-y += posix_types.h
@@ -232,6 +233,7 @@ unifdef-y += if_fddi.h
unifdef-y += if_frad.h
unifdef-y += if_ltalk.h
unifdef-y += if_link.h
+unifdef-y += if_phonet.h
unifdef-y += if_pppol2tp.h
unifdef-y += if_pppox.h
unifdef-y += if_tr.h
diff --git a/include/linux/if_phonet.h b/include/linux/if_phonet.h
index 7e98921..d70034b 100644
--- a/include/linux/if_phonet.h
+++ b/include/linux/if_phonet.h
@@ -5,14 +5,15 @@
*
* Copyright (C) 2008 Nokia Corporation. All rights reserved.
*/
+#ifndef LINUX_IF_PHONET_H
+#define LINUX_IF_PHONET_H
-#define PHONET_HEADER_LEN 8 /* Phonet header length */
-
-#define PHONET_MIN_MTU 6
-/* 6 bytes header + 65535 bytes payload */
-#define PHONET_MAX_MTU 65541
+#define PHONET_MIN_MTU 6 /* pn_length = 0 */
+#define PHONET_MAX_MTU 65541 /* pn_length = 0xffff */
#define PHONET_DEV_MTU PHONET_MAX_MTU
#ifdef __KERNEL__
extern struct header_ops phonet_header_ops;
#endif
+
+#endif
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index b1ea19a..b1770d6 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -54,11 +54,16 @@ errout:
rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
}
-static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
+static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = {
+ [IFA_LOCAL] = { .type = NLA_U8 },
+};
+
+static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
{
- struct rtattr **rta = attr;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
+ struct net *net = sock_net(skb->sk);
+ struct nlattr *tb[IFA_MAX+1];
struct net_device *dev;
+ struct ifaddrmsg *ifm;
int err;
u8 pnaddr;
@@ -67,52 +72,28 @@ static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
ASSERT_RTNL();
- if (rta[IFA_LOCAL - 1] == NULL)
- return -EINVAL;
-
- dev = __dev_get_by_index(&init_net, ifm->ifa_index);
- if (dev == NULL)
- return -ENODEV;
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_phonet_policy);
+ if (err < 0)
+ return err;
- if (ifm->ifa_prefixlen > 0)
+ ifm = nlmsg_data(nlh);
+ if (tb[IFA_LOCAL] == NULL)
return -EINVAL;
-
- memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
-
- err = phonet_address_add(dev, pnaddr);
- if (!err)
- rtmsg_notify(RTM_NEWADDR, dev, pnaddr);
- return err;
-}
-
-static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
-{
- struct rtattr **rta = attr;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
- struct net_device *dev;
- int err;
- u8 pnaddr;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- ASSERT_RTNL();
-
- if (rta[IFA_LOCAL - 1] == NULL)
+ pnaddr = nla_get_u8(tb[IFA_LOCAL]);
+ if (pnaddr & 3)
+ /* Phonet addresses only have 6 high-order bits */
return -EINVAL;
- dev = __dev_get_by_index(&init_net, ifm->ifa_index);
+ dev = __dev_get_by_index(net, ifm->ifa_index);
if (dev == NULL)
return -ENODEV;
- if (ifm->ifa_prefixlen > 0)
- return -EADDRNOTAVAIL;
-
- memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1);
-
- err = phonet_address_del(dev, pnaddr);
+ if (nlh->nlmsg_type == RTM_NEWADDR)
+ err = phonet_address_add(dev, pnaddr);
+ else
+ err = phonet_address_del(dev, pnaddr);
if (!err)
- rtmsg_notify(RTM_DELADDR, dev, pnaddr);
+ rtmsg_notify(nlh->nlmsg_type, dev, pnaddr);
return err;
}
@@ -121,25 +102,23 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
- unsigned int orig_len = skb->len;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg));
- ifm = NLMSG_DATA(nlh);
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), 0);
+ if (nlh == NULL)
+ return -EMSGSIZE;
+
+ ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_PHONET;
ifm->ifa_prefixlen = 0;
ifm->ifa_flags = IFA_F_PERMANENT;
- ifm->ifa_scope = RT_SCOPE_HOST;
+ ifm->ifa_scope = RT_SCOPE_LINK;
ifm->ifa_index = dev->ifindex;
- RTA_PUT(skb, IFA_LOCAL, 1, &addr);
- nlh->nlmsg_len = skb->len - orig_len;
-
- return 0;
-
-nlmsg_failure:
-rtattr_failure:
- skb_trim(skb, orig_len);
+ NLA_PUT_U8(skb, IFA_LOCAL, addr);
+ return nlmsg_end(skb, nlh);
- return -1;
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
}
static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
@@ -180,7 +159,7 @@ out:
void __init phonet_netlink_register(void)
{
- rtnl_register(PF_PHONET, RTM_NEWADDR, newaddr_doit, NULL);
- rtnl_register(PF_PHONET, RTM_DELADDR, deladdr_doit, NULL);
+ rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
+ rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
}
OpenPOWER on IntegriCloud