aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet')
-rw-r--r--net/phonet/pep.c225
1 files changed, 73 insertions, 152 deletions
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index 40952c7d4308..610794a416e8 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -77,24 +77,34 @@ static unsigned char *pep_get_sb(struct sk_buff *skb, u8 *ptype, u8 *plen,
77 return data; 77 return data;
78} 78}
79 79
80static int pep_reply(struct sock *sk, struct sk_buff *oskb, 80static struct sk_buff *pep_alloc_skb(struct sock *sk, const void *payload,
81 u8 code, const void *data, int len, gfp_t priority) 81 int len, gfp_t priority)
82{
83 struct sk_buff *skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
84 if (!skb)
85 return NULL;
86 skb_set_owner_w(skb, sk);
87
88 skb_reserve(skb, MAX_PNPIPE_HEADER);
89 __skb_put(skb, len);
90 skb_copy_to_linear_data(skb, payload, len);
91 __skb_push(skb, sizeof(struct pnpipehdr));
92 skb_reset_transport_header(skb);
93 return skb;
94}
95
96static int pep_reply(struct sock *sk, struct sk_buff *oskb, u8 code,
97 const void *data, int len, gfp_t priority)
82{ 98{
83 const struct pnpipehdr *oph = pnp_hdr(oskb); 99 const struct pnpipehdr *oph = pnp_hdr(oskb);
84 struct pnpipehdr *ph; 100 struct pnpipehdr *ph;
85 struct sk_buff *skb; 101 struct sk_buff *skb;
86 struct sockaddr_pn peer; 102 struct sockaddr_pn peer;
87 103
88 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority); 104 skb = pep_alloc_skb(sk, data, len, priority);
89 if (!skb) 105 if (!skb)
90 return -ENOMEM; 106 return -ENOMEM;
91 skb_set_owner_w(skb, sk);
92 107
93 skb_reserve(skb, MAX_PNPIPE_HEADER);
94 __skb_put(skb, len);
95 skb_copy_to_linear_data(skb, data, len);
96 __skb_push(skb, sizeof(*ph));
97 skb_reset_transport_header(skb);
98 ph = pnp_hdr(skb); 108 ph = pnp_hdr(skb);
99 ph->utid = oph->utid; 109 ph->utid = oph->utid;
100 ph->message_id = oph->message_id + 1; /* REQ -> RESP */ 110 ph->message_id = oph->message_id + 1; /* REQ -> RESP */
@@ -105,135 +115,69 @@ static int pep_reply(struct sock *sk, struct sk_buff *oskb,
105 return pn_skb_send(sk, skb, &peer); 115 return pn_skb_send(sk, skb, &peer);
106} 116}
107 117
108#define PAD 0x00 118static int pep_indicate(struct sock *sk, u8 id, u8 code,
109 119 const void *data, int len, gfp_t priority)
110#ifdef CONFIG_PHONET_PIPECTRLR
111static int pipe_handler_send_req(struct sock *sk, u8 msg_id, gfp_t priority)
112{ 120{
113 int len; 121 struct pep_sock *pn = pep_sk(sk);
114 struct pnpipehdr *ph; 122 struct pnpipehdr *ph;
115 struct sk_buff *skb; 123 struct sk_buff *skb;
116 struct pep_sock *pn = pep_sk(sk);
117
118 static const u8 data[4] = {
119 PAD, PAD, PAD, PAD,
120 };
121 124
122 switch (msg_id) { 125 skb = pep_alloc_skb(sk, data, len, priority);
123 case PNS_PEP_CONNECT_REQ:
124 len = sizeof(data);
125 break;
126
127 case PNS_PEP_DISCONNECT_REQ:
128 case PNS_PEP_ENABLE_REQ:
129 case PNS_PEP_DISABLE_REQ:
130 len = 0;
131 break;
132
133 default:
134 return -EINVAL;
135 }
136
137 skb = alloc_skb(MAX_PNPIPE_HEADER + len, priority);
138 if (!skb) 126 if (!skb)
139 return -ENOMEM; 127 return -ENOMEM;
140 skb_set_owner_w(skb, sk);
141 128
142 skb_reserve(skb, MAX_PNPIPE_HEADER);
143 if (len) {
144 __skb_put(skb, len);
145 skb_copy_to_linear_data(skb, data, len);
146 }
147 __skb_push(skb, sizeof(*ph));
148 skb_reset_transport_header(skb);
149 ph = pnp_hdr(skb); 129 ph = pnp_hdr(skb);
150 ph->utid = msg_id; /* whatever */ 130 ph->utid = 0;
151 ph->message_id = msg_id; 131 ph->message_id = id;
152 ph->pipe_handle = pn->pipe_handle; 132 ph->pipe_handle = pn->pipe_handle;
153 ph->error_code = PN_PIPE_NO_ERROR; 133 ph->data[0] = code;
154
155 return pn_skb_send(sk, skb, NULL); 134 return pn_skb_send(sk, skb, NULL);
156} 135}
157 136
158static int pipe_handler_send_created_ind(struct sock *sk, u8 msg_id) 137#define PAD 0x00
138
139#ifdef CONFIG_PHONET_PIPECTRLR
140static int pipe_handler_request(struct sock *sk, u8 id, u8 code,
141 const void *data, int len)
159{ 142{
160 int err_code; 143 struct pep_sock *pn = pep_sk(sk);
161 struct pnpipehdr *ph; 144 struct pnpipehdr *ph;
162 struct sk_buff *skb; 145 struct sk_buff *skb;
163 146
164 struct pep_sock *pn = pep_sk(sk); 147 skb = pep_alloc_skb(sk, data, len, GFP_KERNEL);
165 static u8 data[4] = {
166 0x03, 0x04,
167 };
168 data[2] = pn->tx_fc;
169 data[3] = pn->rx_fc;
170
171 /*
172 * actually, below is number of sub-blocks and not error code.
173 * Pipe_created_ind message format does not have any
174 * error code field. However, the Phonet stack will always send
175 * an error code as part of pnpipehdr. So, use that err_code to
176 * specify the number of sub-blocks.
177 */
178 err_code = 0x01;
179
180 skb = alloc_skb(MAX_PNPIPE_HEADER + sizeof(data), GFP_ATOMIC);
181 if (!skb) 148 if (!skb)
182 return -ENOMEM; 149 return -ENOMEM;
183 skb_set_owner_w(skb, sk);
184 150
185 skb_reserve(skb, MAX_PNPIPE_HEADER);
186 __skb_put(skb, sizeof(data));
187 skb_copy_to_linear_data(skb, data, sizeof(data));
188 __skb_push(skb, sizeof(*ph));
189 skb_reset_transport_header(skb);
190 ph = pnp_hdr(skb); 151 ph = pnp_hdr(skb);
191 ph->utid = 0; 152 ph->utid = id; /* whatever */
192 ph->message_id = msg_id; 153 ph->message_id = id;
193 ph->pipe_handle = pn->pipe_handle; 154 ph->pipe_handle = pn->pipe_handle;
194 ph->error_code = err_code; 155 ph->data[0] = code;
195
196 return pn_skb_send(sk, skb, NULL); 156 return pn_skb_send(sk, skb, NULL);
197} 157}
198 158
199static int pipe_handler_send_ind(struct sock *sk, u8 msg_id) 159static int pipe_handler_send_created_ind(struct sock *sk)
200{ 160{
201 int err_code;
202 struct pnpipehdr *ph;
203 struct sk_buff *skb;
204 struct pep_sock *pn = pep_sk(sk); 161 struct pep_sock *pn = pep_sk(sk);
162 u8 data[4] = {
163 PN_PIPE_SB_NEGOTIATED_FC, pep_sb_size(2),
164 pn->tx_fc, pn->rx_fc,
165 };
205 166
206 /* 167 return pep_indicate(sk, PNS_PIPE_CREATED_IND, 1 /* sub-blocks */,
207 * actually, below is a filler. 168 data, 4, GFP_ATOMIC);
208 * Pipe_enabled/disabled_ind message format does not have any 169}
209 * error code field. However, the Phonet stack will always send
210 * an error code as part of pnpipehdr. So, use that err_code to
211 * specify the filler value.
212 */
213 err_code = 0x0;
214
215 skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
216 if (!skb)
217 return -ENOMEM;
218 skb_set_owner_w(skb, sk);
219
220 skb_reserve(skb, MAX_PNPIPE_HEADER);
221 __skb_push(skb, sizeof(*ph));
222 skb_reset_transport_header(skb);
223 ph = pnp_hdr(skb);
224 ph->utid = 0;
225 ph->message_id = msg_id;
226 ph->pipe_handle = pn->pipe_handle;
227 ph->error_code = err_code;
228 170
229 return pn_skb_send(sk, skb, NULL); 171static int pipe_handler_send_ind(struct sock *sk, u8 id)
172{
173 return pep_indicate(sk, id, PAD, NULL, 0, GFP_ATOMIC);
230} 174}
231 175
232static int pipe_handler_enable_pipe(struct sock *sk, int enable) 176static int pipe_handler_enable_pipe(struct sock *sk, int enable)
233{ 177{
234 u8 id = enable ? PNS_PEP_ENABLE_REQ : PNS_PEP_DISABLE_REQ; 178 u8 id = enable ? PNS_PEP_ENABLE_REQ : PNS_PEP_DISABLE_REQ;
235 179
236 return pipe_handler_send_req(sk, id, GFP_KERNEL); 180 return pipe_handler_request(sk, id, PAD, NULL, 0);
237} 181}
238#endif 182#endif
239 183
@@ -274,23 +218,21 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
274 struct sk_buff *skb; 218 struct sk_buff *skb;
275 struct pnpipehdr *ph; 219 struct pnpipehdr *ph;
276 struct sockaddr_pn dst; 220 struct sockaddr_pn dst;
221 u8 data[4] = {
222 oph->data[0], /* PEP type */
223 code, /* error code, at an unusual offset */
224 PAD, PAD,
225 };
277 226
278 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); 227 skb = pep_alloc_skb(sk, data, 4, priority);
279 if (!skb) 228 if (!skb)
280 return -ENOMEM; 229 return -ENOMEM;
281 skb_set_owner_w(skb, sk);
282
283 skb_reserve(skb, MAX_PHONET_HEADER);
284 ph = (struct pnpipehdr *)skb_put(skb, sizeof(*ph) + 4);
285 230
231 ph = pnp_hdr(skb);
286 ph->utid = oph->utid; 232 ph->utid = oph->utid;
287 ph->message_id = PNS_PEP_CTRL_RESP; 233 ph->message_id = PNS_PEP_CTRL_RESP;
288 ph->pipe_handle = oph->pipe_handle; 234 ph->pipe_handle = oph->pipe_handle;
289 ph->data[0] = oph->data[1]; /* CTRL id */ 235 ph->data[0] = oph->data[1]; /* CTRL id */
290 ph->data[1] = oph->data[0]; /* PEP type */
291 ph->data[2] = code; /* error code, at an usual offset */
292 ph->data[3] = PAD;
293 ph->data[4] = PAD;
294 236
295 pn_skb_get_src_sockaddr(oskb, &dst); 237 pn_skb_get_src_sockaddr(oskb, &dst);
296 return pn_skb_send(sk, skb, &dst); 238 return pn_skb_send(sk, skb, &dst);
@@ -298,34 +240,15 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
298 240
299static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority) 241static int pipe_snd_status(struct sock *sk, u8 type, u8 status, gfp_t priority)
300{ 242{
301 struct pep_sock *pn = pep_sk(sk); 243 u8 data[4] = { type, PAD, PAD, status };
302 struct pnpipehdr *ph;
303 struct sk_buff *skb;
304 244
305 skb = alloc_skb(MAX_PNPIPE_HEADER + 4, priority); 245 return pep_indicate(sk, PNS_PEP_STATUS_IND, PN_PEP_TYPE_COMMON,
306 if (!skb) 246 data, 4, priority);
307 return -ENOMEM;
308 skb_set_owner_w(skb, sk);
309
310 skb_reserve(skb, MAX_PNPIPE_HEADER + 4);
311 __skb_push(skb, sizeof(*ph) + 4);
312 skb_reset_transport_header(skb);
313 ph = pnp_hdr(skb);
314 ph->utid = 0;
315 ph->message_id = PNS_PEP_STATUS_IND;
316 ph->pipe_handle = pn->pipe_handle;
317 ph->pep_type = PN_PEP_TYPE_COMMON;
318 ph->data[1] = type;
319 ph->data[2] = PAD;
320 ph->data[3] = PAD;
321 ph->data[4] = status;
322
323 return pn_skb_send(sk, skb, NULL);
324} 247}
325 248
326/* Send our RX flow control information to the sender. 249/* Send our RX flow control information to the sender.
327 * Socket must be locked. */ 250 * Socket must be locked. */
328static void pipe_grant_credits(struct sock *sk) 251static void pipe_grant_credits(struct sock *sk, gfp_t priority)
329{ 252{
330 struct pep_sock *pn = pep_sk(sk); 253 struct pep_sock *pn = pep_sk(sk);
331 254
@@ -335,16 +258,16 @@ static void pipe_grant_credits(struct sock *sk)
335 case PN_LEGACY_FLOW_CONTROL: /* TODO */ 258 case PN_LEGACY_FLOW_CONTROL: /* TODO */
336 break; 259 break;
337 case PN_ONE_CREDIT_FLOW_CONTROL: 260 case PN_ONE_CREDIT_FLOW_CONTROL:
338 pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL, 261 if (pipe_snd_status(sk, PN_PEP_IND_FLOW_CONTROL,
339 PEP_IND_READY, GFP_ATOMIC); 262 PEP_IND_READY, priority) == 0)
340 pn->rx_credits = 1; 263 pn->rx_credits = 1;
341 break; 264 break;
342 case PN_MULTI_CREDIT_FLOW_CONTROL: 265 case PN_MULTI_CREDIT_FLOW_CONTROL:
343 if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX) 266 if ((pn->rx_credits + CREDITS_THR) > CREDITS_MAX)
344 break; 267 break;
345 if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS, 268 if (pipe_snd_status(sk, PN_PEP_IND_ID_MCFC_GRANT_CREDITS,
346 CREDITS_MAX - pn->rx_credits, 269 CREDITS_MAX - pn->rx_credits,
347 GFP_ATOMIC) == 0) 270 priority) == 0)
348 pn->rx_credits = CREDITS_MAX; 271 pn->rx_credits = CREDITS_MAX;
349 break; 272 break;
350 } 273 }
@@ -474,7 +397,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
474 if (sk->sk_state == TCP_ESTABLISHED) 397 if (sk->sk_state == TCP_ESTABLISHED)
475 break; /* Nothing to do */ 398 break; /* Nothing to do */
476 sk->sk_state = TCP_ESTABLISHED; 399 sk->sk_state = TCP_ESTABLISHED;
477 pipe_grant_credits(sk); 400 pipe_grant_credits(sk, GFP_ATOMIC);
478 break; 401 break;
479#endif 402#endif
480 403
@@ -561,7 +484,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
561 if (sk->sk_state == TCP_ESTABLISHED) 484 if (sk->sk_state == TCP_ESTABLISHED)
562 break; /* Nothing to do */ 485 break; /* Nothing to do */
563 sk->sk_state = TCP_ESTABLISHED; 486 sk->sk_state = TCP_ESTABLISHED;
564 pipe_grant_credits(sk); 487 pipe_grant_credits(sk, GFP_ATOMIC);
565 break; 488 break;
566 489
567 case PNS_PIPE_DISABLED_IND: 490 case PNS_PIPE_DISABLED_IND:
@@ -655,7 +578,7 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
655 pn->rx_credits = 0; 578 pn->rx_credits = 0;
656 sk->sk_state_change(sk); 579 sk->sk_state_change(sk);
657 580
658 return pipe_handler_send_created_ind(sk, PNS_PIPE_CREATED_IND); 581 return pipe_handler_send_created_ind(sk);
659} 582}
660#endif 583#endif
661 584
@@ -853,19 +776,15 @@ static int pipe_do_remove(struct sock *sk)
853 struct pnpipehdr *ph; 776 struct pnpipehdr *ph;
854 struct sk_buff *skb; 777 struct sk_buff *skb;
855 778
856 skb = alloc_skb(MAX_PNPIPE_HEADER, GFP_KERNEL); 779 skb = pep_alloc_skb(sk, NULL, 0, GFP_KERNEL);
857 if (!skb) 780 if (!skb)
858 return -ENOMEM; 781 return -ENOMEM;
859 782
860 skb_reserve(skb, MAX_PNPIPE_HEADER);
861 __skb_push(skb, sizeof(*ph));
862 skb_reset_transport_header(skb);
863 ph = pnp_hdr(skb); 783 ph = pnp_hdr(skb);
864 ph->utid = 0; 784 ph->utid = 0;
865 ph->message_id = PNS_PIPE_REMOVE_REQ; 785 ph->message_id = PNS_PIPE_REMOVE_REQ;
866 ph->pipe_handle = pn->pipe_handle; 786 ph->pipe_handle = pn->pipe_handle;
867 ph->data[0] = PAD; 787 ph->data[0] = PAD;
868
869 return pn_skb_send(sk, skb, NULL); 788 return pn_skb_send(sk, skb, NULL);
870} 789}
871#endif 790#endif
@@ -894,7 +813,7 @@ static void pep_sock_close(struct sock *sk, long timeout)
894 pipe_do_remove(sk); 813 pipe_do_remove(sk);
895#else 814#else
896 /* send pep disconnect request */ 815 /* send pep disconnect request */
897 pipe_handler_send_req(sk, PNS_PEP_DISCONNECT_REQ, GFP_KERNEL); 816 pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD, NULL, 0);
898 sk->sk_state = TCP_CLOSE; 817 sk->sk_state = TCP_CLOSE;
899#endif 818#endif
900 } 819 }
@@ -980,10 +899,12 @@ static int pep_sock_connect(struct sock *sk, struct sockaddr *addr, int len)
980{ 899{
981 struct pep_sock *pn = pep_sk(sk); 900 struct pep_sock *pn = pep_sk(sk);
982 const struct sockaddr_pn *spn = (struct sockaddr_pn *)addr; 901 const struct sockaddr_pn *spn = (struct sockaddr_pn *)addr;
902 u8 data[4] = { 0 /* sub-blocks */, PAD, PAD, PAD };
983 903
984 pn->pn_sk.dobject = pn_sockaddr_get_object(spn); 904 pn->pn_sk.dobject = pn_sockaddr_get_object(spn);
985 pn->pn_sk.resource = pn_sockaddr_get_resource(spn); 905 pn->pn_sk.resource = pn_sockaddr_get_resource(spn);
986 return pipe_handler_send_req(sk, PNS_PEP_CONNECT_REQ, GFP_KERNEL); 906 return pipe_handler_request(sk, PNS_PEP_CONNECT_REQ,
907 PN_PIPE_DISABLE, data, 4);
987} 908}
988#endif 909#endif
989 910
@@ -1280,7 +1201,7 @@ struct sk_buff *pep_read(struct sock *sk)
1280 struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); 1201 struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue);
1281 1202
1282 if (sk->sk_state == TCP_ESTABLISHED) 1203 if (sk->sk_state == TCP_ESTABLISHED)
1283 pipe_grant_credits(sk); 1204 pipe_grant_credits(sk, GFP_ATOMIC);
1284 return skb; 1205 return skb;
1285} 1206}
1286 1207
@@ -1325,7 +1246,7 @@ static int pep_recvmsg(struct kiocb *iocb, struct sock *sk,
1325 } 1246 }
1326 1247
1327 if (sk->sk_state == TCP_ESTABLISHED) 1248 if (sk->sk_state == TCP_ESTABLISHED)
1328 pipe_grant_credits(sk); 1249 pipe_grant_credits(sk, GFP_KERNEL);
1329 release_sock(sk); 1250 release_sock(sk);
1330copy: 1251copy:
1331 msg->msg_flags |= MSG_EOR; 1252 msg->msg_flags |= MSG_EOR;