aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/phonet/pn_netlink.c91
1 files changed, 35 insertions, 56 deletions
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index b1ea19a230d..b1770d66bc8 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -54,11 +54,16 @@ errout:
54 rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err); 54 rtnl_set_sk_err(dev_net(dev), RTNLGRP_PHONET_IFADDR, err);
55} 55}
56 56
57static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr) 57static const struct nla_policy ifa_phonet_policy[IFA_MAX+1] = {
58 [IFA_LOCAL] = { .type = NLA_U8 },
59};
60
61static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
58{ 62{
59 struct rtattr **rta = attr; 63 struct net *net = sock_net(skb->sk);
60 struct ifaddrmsg *ifm = NLMSG_DATA(nlm); 64 struct nlattr *tb[IFA_MAX+1];
61 struct net_device *dev; 65 struct net_device *dev;
66 struct ifaddrmsg *ifm;
62 int err; 67 int err;
63 u8 pnaddr; 68 u8 pnaddr;
64 69
@@ -67,52 +72,28 @@ static int newaddr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
67 72
68 ASSERT_RTNL(); 73 ASSERT_RTNL();
69 74
70 if (rta[IFA_LOCAL - 1] == NULL) 75 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_phonet_policy);
71 return -EINVAL; 76 if (err < 0)
72 77 return err;
73 dev = __dev_get_by_index(&init_net, ifm->ifa_index);
74 if (dev == NULL)
75 return -ENODEV;
76 78
77 if (ifm->ifa_prefixlen > 0) 79 ifm = nlmsg_data(nlh);
80 if (tb[IFA_LOCAL] == NULL)
78 return -EINVAL; 81 return -EINVAL;
79 82 pnaddr = nla_get_u8(tb[IFA_LOCAL]);
80 memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); 83 if (pnaddr & 3)
81 84 /* Phonet addresses only have 6 high-order bits */
82 err = phonet_address_add(dev, pnaddr);
83 if (!err)
84 rtmsg_notify(RTM_NEWADDR, dev, pnaddr);
85 return err;
86}
87
88static int deladdr_doit(struct sk_buff *skb, struct nlmsghdr *nlm, void *attr)
89{
90 struct rtattr **rta = attr;
91 struct ifaddrmsg *ifm = NLMSG_DATA(nlm);
92 struct net_device *dev;
93 int err;
94 u8 pnaddr;
95
96 if (!capable(CAP_SYS_ADMIN))
97 return -EPERM;
98
99 ASSERT_RTNL();
100
101 if (rta[IFA_LOCAL - 1] == NULL)
102 return -EINVAL; 85 return -EINVAL;
103 86
104 dev = __dev_get_by_index(&init_net, ifm->ifa_index); 87 dev = __dev_get_by_index(net, ifm->ifa_index);
105 if (dev == NULL) 88 if (dev == NULL)
106 return -ENODEV; 89 return -ENODEV;
107 90
108 if (ifm->ifa_prefixlen > 0) 91 if (nlh->nlmsg_type == RTM_NEWADDR)
109 return -EADDRNOTAVAIL; 92 err = phonet_address_add(dev, pnaddr);
110 93 else
111 memcpy(&pnaddr, RTA_DATA(rta[IFA_LOCAL - 1]), 1); 94 err = phonet_address_del(dev, pnaddr);
112
113 err = phonet_address_del(dev, pnaddr);
114 if (!err) 95 if (!err)
115 rtmsg_notify(RTM_DELADDR, dev, pnaddr); 96 rtmsg_notify(nlh->nlmsg_type, dev, pnaddr);
116 return err; 97 return err;
117} 98}
118 99
@@ -121,25 +102,23 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
121{ 102{
122 struct ifaddrmsg *ifm; 103 struct ifaddrmsg *ifm;
123 struct nlmsghdr *nlh; 104 struct nlmsghdr *nlh;
124 unsigned int orig_len = skb->len;
125 105
126 nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(struct ifaddrmsg)); 106 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), 0);
127 ifm = NLMSG_DATA(nlh); 107 if (nlh == NULL)
108 return -EMSGSIZE;
109
110 ifm = nlmsg_data(nlh);
128 ifm->ifa_family = AF_PHONET; 111 ifm->ifa_family = AF_PHONET;
129 ifm->ifa_prefixlen = 0; 112 ifm->ifa_prefixlen = 0;
130 ifm->ifa_flags = IFA_F_PERMANENT; 113 ifm->ifa_flags = IFA_F_PERMANENT;
131 ifm->ifa_scope = RT_SCOPE_HOST; 114 ifm->ifa_scope = RT_SCOPE_LINK;
132 ifm->ifa_index = dev->ifindex; 115 ifm->ifa_index = dev->ifindex;
133 RTA_PUT(skb, IFA_LOCAL, 1, &addr); 116 NLA_PUT_U8(skb, IFA_LOCAL, addr);
134 nlh->nlmsg_len = skb->len - orig_len; 117 return nlmsg_end(skb, nlh);
135
136 return 0;
137
138nlmsg_failure:
139rtattr_failure:
140 skb_trim(skb, orig_len);
141 118
142 return -1; 119nla_put_failure:
120 nlmsg_cancel(skb, nlh);
121 return -EMSGSIZE;
143} 122}
144 123
145static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 124static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
@@ -180,7 +159,7 @@ out:
180 159
181void __init phonet_netlink_register(void) 160void __init phonet_netlink_register(void)
182{ 161{
183 rtnl_register(PF_PHONET, RTM_NEWADDR, newaddr_doit, NULL); 162 rtnl_register(PF_PHONET, RTM_NEWADDR, addr_doit, NULL);
184 rtnl_register(PF_PHONET, RTM_DELADDR, deladdr_doit, NULL); 163 rtnl_register(PF_PHONET, RTM_DELADDR, addr_doit, NULL);
185 rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit); 164 rtnl_register(PF_PHONET, RTM_GETADDR, NULL, getaddr_dumpit);
186} 165}