diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-05-14 11:43:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-15 15:51:43 -0400 |
commit | 1cc76e365405eae54a15e86b5d75ee885cd7d891 (patch) | |
tree | 0870bee3e462afd904eceb63e832aae521978931 /net/ieee802154 | |
parent | d4b2816d67d6e07b2f27037f282d8db03a5829d7 (diff) |
ieee802154: fix dgram socket sendmsg()
802.15.4 datagram sockets do not currently have a compliant sendmsg().
The destination address supplied is always ignored, and in unconnected
mode, packets are broadcast instead of dropped with -EDESTADDRREQ. This
patch fixes 802.15.4 dgram sockets to be compliant, i.e.
!conn && !msg_name => -EDESTADDRREQ
!conn && msg_name => send to msg_name
conn && !msg_name => send to connected
conn && msg_name => -EISCONN
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/dgram.c | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index d95e2e1bdf54..76c77256a56e 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -45,6 +45,7 @@ struct dgram_sock { | |||
45 | struct ieee802154_addr dst_addr; | 45 | struct ieee802154_addr dst_addr; |
46 | 46 | ||
47 | unsigned int bound:1; | 47 | unsigned int bound:1; |
48 | unsigned int connected:1; | ||
48 | unsigned int want_ack:1; | 49 | unsigned int want_ack:1; |
49 | }; | 50 | }; |
50 | 51 | ||
@@ -73,10 +74,7 @@ static int dgram_init(struct sock *sk) | |||
73 | { | 74 | { |
74 | struct dgram_sock *ro = dgram_sk(sk); | 75 | struct dgram_sock *ro = dgram_sk(sk); |
75 | 76 | ||
76 | ro->dst_addr.mode = IEEE802154_ADDR_LONG; | ||
77 | ro->dst_addr.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); | ||
78 | ro->want_ack = 1; | 77 | ro->want_ack = 1; |
79 | memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN); | ||
80 | return 0; | 78 | return 0; |
81 | } | 79 | } |
82 | 80 | ||
@@ -183,6 +181,7 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, | |||
183 | } | 181 | } |
184 | 182 | ||
185 | ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr); | 183 | ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr); |
184 | ro->connected = 1; | ||
186 | 185 | ||
187 | out: | 186 | out: |
188 | release_sock(sk); | 187 | release_sock(sk); |
@@ -194,10 +193,7 @@ static int dgram_disconnect(struct sock *sk, int flags) | |||
194 | struct dgram_sock *ro = dgram_sk(sk); | 193 | struct dgram_sock *ro = dgram_sk(sk); |
195 | 194 | ||
196 | lock_sock(sk); | 195 | lock_sock(sk); |
197 | 196 | ro->connected = 0; | |
198 | ro->dst_addr.mode = IEEE802154_ADDR_LONG; | ||
199 | memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN); | ||
200 | |||
201 | release_sock(sk); | 197 | release_sock(sk); |
202 | 198 | ||
203 | return 0; | 199 | return 0; |
@@ -211,6 +207,7 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
211 | struct sk_buff *skb; | 207 | struct sk_buff *skb; |
212 | struct ieee802154_mac_cb *cb; | 208 | struct ieee802154_mac_cb *cb; |
213 | struct dgram_sock *ro = dgram_sk(sk); | 209 | struct dgram_sock *ro = dgram_sk(sk); |
210 | struct ieee802154_addr dst_addr; | ||
214 | int hlen, tlen; | 211 | int hlen, tlen; |
215 | int err; | 212 | int err; |
216 | 213 | ||
@@ -219,6 +216,11 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
219 | return -EOPNOTSUPP; | 216 | return -EOPNOTSUPP; |
220 | } | 217 | } |
221 | 218 | ||
219 | if (!ro->connected && !msg->msg_name) | ||
220 | return -EDESTADDRREQ; | ||
221 | else if (ro->connected && msg->msg_name) | ||
222 | return -EISCONN; | ||
223 | |||
222 | if (!ro->bound) | 224 | if (!ro->bound) |
223 | dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); | 225 | dev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_IEEE802154); |
224 | else | 226 | else |
@@ -254,8 +256,16 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
254 | cb->type = IEEE802154_FC_TYPE_DATA; | 256 | cb->type = IEEE802154_FC_TYPE_DATA; |
255 | cb->ackreq = ro->want_ack; | 257 | cb->ackreq = ro->want_ack; |
256 | 258 | ||
257 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &ro->dst_addr, | 259 | if (msg->msg_name) { |
258 | ro->bound ? &ro->src_addr : NULL, size); | 260 | DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name); |
261 | |||
262 | ieee802154_addr_from_sa(&dst_addr, &daddr->addr); | ||
263 | } else { | ||
264 | dst_addr = ro->dst_addr; | ||
265 | } | ||
266 | |||
267 | err = dev_hard_header(skb, dev, ETH_P_IEEE802154, &dst_addr, | ||
268 | ro->bound ? &ro->src_addr : NULL, size); | ||
259 | if (err < 0) | 269 | if (err < 0) |
260 | goto out_skb; | 270 | goto out_skb; |
261 | 271 | ||