1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * |
4 | * Author Karsten Keil <kkeil@novell.com> |
5 | * |
6 | * Copyright 2008 by Karsten Keil <kkeil@novell.com> |
7 | */ |
8 | |
9 | #include <linux/mISDNif.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/export.h> |
12 | #include "core.h" |
13 | |
14 | static u_int *debug; |
15 | |
16 | static struct proto mISDN_proto = { |
17 | .name = "misdn" , |
18 | .owner = THIS_MODULE, |
19 | .obj_size = sizeof(struct mISDN_sock) |
20 | }; |
21 | |
22 | #define _pms(sk) ((struct mISDN_sock *)sk) |
23 | |
24 | static struct mISDN_sock_list data_sockets = { |
25 | .lock = __RW_LOCK_UNLOCKED(data_sockets.lock) |
26 | }; |
27 | |
28 | static struct mISDN_sock_list base_sockets = { |
29 | .lock = __RW_LOCK_UNLOCKED(base_sockets.lock) |
30 | }; |
31 | |
32 | #define 4 |
33 | |
34 | static inline struct sk_buff * |
35 | _l2_alloc_skb(unsigned int len, gfp_t gfp_mask) |
36 | { |
37 | struct sk_buff *skb; |
38 | |
39 | skb = alloc_skb(size: len + L2_HEADER_LEN, priority: gfp_mask); |
40 | if (likely(skb)) |
41 | skb_reserve(skb, L2_HEADER_LEN); |
42 | return skb; |
43 | } |
44 | |
45 | static void |
46 | mISDN_sock_link(struct mISDN_sock_list *l, struct sock *sk) |
47 | { |
48 | write_lock_bh(&l->lock); |
49 | sk_add_node(sk, list: &l->head); |
50 | write_unlock_bh(&l->lock); |
51 | } |
52 | |
53 | static void mISDN_sock_unlink(struct mISDN_sock_list *l, struct sock *sk) |
54 | { |
55 | write_lock_bh(&l->lock); |
56 | sk_del_node_init(sk); |
57 | write_unlock_bh(&l->lock); |
58 | } |
59 | |
60 | static int |
61 | mISDN_send(struct mISDNchannel *ch, struct sk_buff *skb) |
62 | { |
63 | struct mISDN_sock *msk; |
64 | int err; |
65 | |
66 | msk = container_of(ch, struct mISDN_sock, ch); |
67 | if (*debug & DEBUG_SOCKET) |
68 | printk(KERN_DEBUG "%s len %d %p\n" , __func__, skb->len, skb); |
69 | if (msk->sk.sk_state == MISDN_CLOSED) |
70 | return -EUNATCH; |
71 | __net_timestamp(skb); |
72 | err = sock_queue_rcv_skb(sk: &msk->sk, skb); |
73 | if (err) |
74 | printk(KERN_WARNING "%s: error %d\n" , __func__, err); |
75 | return err; |
76 | } |
77 | |
78 | static int |
79 | mISDN_ctrl(struct mISDNchannel *ch, u_int cmd, void *arg) |
80 | { |
81 | struct mISDN_sock *msk; |
82 | |
83 | msk = container_of(ch, struct mISDN_sock, ch); |
84 | if (*debug & DEBUG_SOCKET) |
85 | printk(KERN_DEBUG "%s(%p, %x, %p)\n" , __func__, ch, cmd, arg); |
86 | switch (cmd) { |
87 | case CLOSE_CHANNEL: |
88 | msk->sk.sk_state = MISDN_CLOSED; |
89 | break; |
90 | } |
91 | return 0; |
92 | } |
93 | |
94 | static inline void |
95 | mISDN_sock_cmsg(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) |
96 | { |
97 | struct __kernel_old_timeval tv; |
98 | |
99 | if (_pms(sk)->cmask & MISDN_TIME_STAMP) { |
100 | skb_get_timestamp(skb, stamp: &tv); |
101 | put_cmsg(msg, SOL_MISDN, MISDN_TIME_STAMP, len: sizeof(tv), data: &tv); |
102 | } |
103 | } |
104 | |
105 | static int |
106 | mISDN_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, |
107 | int flags) |
108 | { |
109 | struct sk_buff *skb; |
110 | struct sock *sk = sock->sk; |
111 | |
112 | int copied, err; |
113 | |
114 | if (*debug & DEBUG_SOCKET) |
115 | printk(KERN_DEBUG "%s: len %d, flags %x ch.nr %d, proto %x\n" , |
116 | __func__, (int)len, flags, _pms(sk)->ch.nr, |
117 | sk->sk_protocol); |
118 | if (flags & (MSG_OOB)) |
119 | return -EOPNOTSUPP; |
120 | |
121 | if (sk->sk_state == MISDN_CLOSED) |
122 | return 0; |
123 | |
124 | skb = skb_recv_datagram(sk, flags, err: &err); |
125 | if (!skb) |
126 | return err; |
127 | |
128 | if (msg->msg_name) { |
129 | DECLARE_SOCKADDR(struct sockaddr_mISDN *, maddr, msg->msg_name); |
130 | |
131 | maddr->family = AF_ISDN; |
132 | maddr->dev = _pms(sk)->dev->id; |
133 | if ((sk->sk_protocol == ISDN_P_LAPD_TE) || |
134 | (sk->sk_protocol == ISDN_P_LAPD_NT)) { |
135 | maddr->channel = (mISDN_HEAD_ID(skb) >> 16) & 0xff; |
136 | maddr->tei = (mISDN_HEAD_ID(skb) >> 8) & 0xff; |
137 | maddr->sapi = mISDN_HEAD_ID(skb) & 0xff; |
138 | } else { |
139 | maddr->channel = _pms(sk)->ch.nr; |
140 | maddr->sapi = _pms(sk)->ch.addr & 0xFF; |
141 | maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF; |
142 | } |
143 | msg->msg_namelen = sizeof(*maddr); |
144 | } |
145 | |
146 | copied = skb->len + MISDN_HEADER_LEN; |
147 | if (len < copied) { |
148 | if (flags & MSG_PEEK) |
149 | refcount_dec(r: &skb->users); |
150 | else |
151 | skb_queue_head(list: &sk->sk_receive_queue, newsk: skb); |
152 | return -ENOSPC; |
153 | } |
154 | memcpy(skb_push(skb, MISDN_HEADER_LEN), mISDN_HEAD_P(skb), |
155 | MISDN_HEADER_LEN); |
156 | |
157 | err = skb_copy_datagram_msg(from: skb, offset: 0, msg, size: copied); |
158 | |
159 | mISDN_sock_cmsg(sk, msg, skb); |
160 | |
161 | skb_free_datagram(sk, skb); |
162 | |
163 | return err ? : copied; |
164 | } |
165 | |
166 | static int |
167 | mISDN_sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) |
168 | { |
169 | struct sock *sk = sock->sk; |
170 | struct sk_buff *skb; |
171 | int err = -ENOMEM; |
172 | |
173 | if (*debug & DEBUG_SOCKET) |
174 | printk(KERN_DEBUG "%s: len %d flags %x ch %d proto %x\n" , |
175 | __func__, (int)len, msg->msg_flags, _pms(sk)->ch.nr, |
176 | sk->sk_protocol); |
177 | |
178 | if (msg->msg_flags & MSG_OOB) |
179 | return -EOPNOTSUPP; |
180 | |
181 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_NOSIGNAL | MSG_ERRQUEUE)) |
182 | return -EINVAL; |
183 | |
184 | if (len < MISDN_HEADER_LEN) |
185 | return -EINVAL; |
186 | |
187 | if (sk->sk_state != MISDN_BOUND) |
188 | return -EBADFD; |
189 | |
190 | lock_sock(sk); |
191 | |
192 | skb = _l2_alloc_skb(len, GFP_KERNEL); |
193 | if (!skb) |
194 | goto done; |
195 | |
196 | if (memcpy_from_msg(data: skb_put(skb, len), msg, len)) { |
197 | err = -EFAULT; |
198 | goto done; |
199 | } |
200 | |
201 | memcpy(mISDN_HEAD_P(skb), skb->data, MISDN_HEADER_LEN); |
202 | skb_pull(skb, MISDN_HEADER_LEN); |
203 | |
204 | if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) { |
205 | /* if we have a address, we use it */ |
206 | DECLARE_SOCKADDR(struct sockaddr_mISDN *, maddr, msg->msg_name); |
207 | mISDN_HEAD_ID(skb) = maddr->channel; |
208 | } else { /* use default for L2 messages */ |
209 | if ((sk->sk_protocol == ISDN_P_LAPD_TE) || |
210 | (sk->sk_protocol == ISDN_P_LAPD_NT)) |
211 | mISDN_HEAD_ID(skb) = _pms(sk)->ch.nr; |
212 | } |
213 | |
214 | if (*debug & DEBUG_SOCKET) |
215 | printk(KERN_DEBUG "%s: ID:%x\n" , |
216 | __func__, mISDN_HEAD_ID(skb)); |
217 | |
218 | err = -ENODEV; |
219 | if (!_pms(sk)->ch.peer) |
220 | goto done; |
221 | err = _pms(sk)->ch.recv(_pms(sk)->ch.peer, skb); |
222 | if (err) |
223 | goto done; |
224 | else { |
225 | skb = NULL; |
226 | err = len; |
227 | } |
228 | |
229 | done: |
230 | kfree_skb(skb); |
231 | release_sock(sk); |
232 | return err; |
233 | } |
234 | |
235 | static int |
236 | data_sock_release(struct socket *sock) |
237 | { |
238 | struct sock *sk = sock->sk; |
239 | |
240 | if (*debug & DEBUG_SOCKET) |
241 | printk(KERN_DEBUG "%s(%p) sk=%p\n" , __func__, sock, sk); |
242 | if (!sk) |
243 | return 0; |
244 | switch (sk->sk_protocol) { |
245 | case ISDN_P_TE_S0: |
246 | case ISDN_P_NT_S0: |
247 | case ISDN_P_TE_E1: |
248 | case ISDN_P_NT_E1: |
249 | if (sk->sk_state == MISDN_BOUND) |
250 | delete_channel(&_pms(sk)->ch); |
251 | else |
252 | mISDN_sock_unlink(l: &data_sockets, sk); |
253 | break; |
254 | case ISDN_P_LAPD_TE: |
255 | case ISDN_P_LAPD_NT: |
256 | case ISDN_P_B_RAW: |
257 | case ISDN_P_B_HDLC: |
258 | case ISDN_P_B_X75SLP: |
259 | case ISDN_P_B_L2DTMF: |
260 | case ISDN_P_B_L2DSP: |
261 | case ISDN_P_B_L2DSPHDLC: |
262 | delete_channel(&_pms(sk)->ch); |
263 | mISDN_sock_unlink(l: &data_sockets, sk); |
264 | break; |
265 | } |
266 | |
267 | lock_sock(sk); |
268 | |
269 | sock_orphan(sk); |
270 | skb_queue_purge(list: &sk->sk_receive_queue); |
271 | |
272 | release_sock(sk); |
273 | sock_put(sk); |
274 | |
275 | return 0; |
276 | } |
277 | |
278 | static int |
279 | data_sock_ioctl_bound(struct sock *sk, unsigned int cmd, void __user *p) |
280 | { |
281 | struct mISDN_ctrl_req cq; |
282 | int err = -EINVAL, val[2]; |
283 | struct mISDNchannel *bchan, *next; |
284 | |
285 | lock_sock(sk); |
286 | if (!_pms(sk)->dev) { |
287 | err = -ENODEV; |
288 | goto done; |
289 | } |
290 | switch (cmd) { |
291 | case IMCTRLREQ: |
292 | if (copy_from_user(to: &cq, from: p, n: sizeof(cq))) { |
293 | err = -EFAULT; |
294 | break; |
295 | } |
296 | if ((sk->sk_protocol & ~ISDN_P_B_MASK) == ISDN_P_B_START) { |
297 | list_for_each_entry_safe(bchan, next, |
298 | &_pms(sk)->dev->bchannels, list) { |
299 | if (bchan->nr == cq.channel) { |
300 | err = bchan->ctrl(bchan, |
301 | CONTROL_CHANNEL, &cq); |
302 | break; |
303 | } |
304 | } |
305 | } else |
306 | err = _pms(sk)->dev->D.ctrl(&_pms(sk)->dev->D, |
307 | CONTROL_CHANNEL, &cq); |
308 | if (err) |
309 | break; |
310 | if (copy_to_user(to: p, from: &cq, n: sizeof(cq))) |
311 | err = -EFAULT; |
312 | break; |
313 | case IMCLEAR_L2: |
314 | if (sk->sk_protocol != ISDN_P_LAPD_NT) { |
315 | err = -EINVAL; |
316 | break; |
317 | } |
318 | val[0] = cmd; |
319 | if (get_user(val[1], (int __user *)p)) { |
320 | err = -EFAULT; |
321 | break; |
322 | } |
323 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, |
324 | CONTROL_CHANNEL, val); |
325 | break; |
326 | case IMHOLD_L1: |
327 | if (sk->sk_protocol != ISDN_P_LAPD_NT |
328 | && sk->sk_protocol != ISDN_P_LAPD_TE) { |
329 | err = -EINVAL; |
330 | break; |
331 | } |
332 | val[0] = cmd; |
333 | if (get_user(val[1], (int __user *)p)) { |
334 | err = -EFAULT; |
335 | break; |
336 | } |
337 | err = _pms(sk)->dev->teimgr->ctrl(_pms(sk)->dev->teimgr, |
338 | CONTROL_CHANNEL, val); |
339 | break; |
340 | default: |
341 | err = -EINVAL; |
342 | break; |
343 | } |
344 | done: |
345 | release_sock(sk); |
346 | return err; |
347 | } |
348 | |
349 | static int |
350 | data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
351 | { |
352 | int err = 0, id; |
353 | struct sock *sk = sock->sk; |
354 | struct mISDNdevice *dev; |
355 | struct mISDNversion ver; |
356 | |
357 | switch (cmd) { |
358 | case IMGETVERSION: |
359 | ver.major = MISDN_MAJOR_VERSION; |
360 | ver.minor = MISDN_MINOR_VERSION; |
361 | ver.release = MISDN_RELEASE; |
362 | if (copy_to_user(to: (void __user *)arg, from: &ver, n: sizeof(ver))) |
363 | err = -EFAULT; |
364 | break; |
365 | case IMGETCOUNT: |
366 | id = get_mdevice_count(); |
367 | if (put_user(id, (int __user *)arg)) |
368 | err = -EFAULT; |
369 | break; |
370 | case IMGETDEVINFO: |
371 | if (get_user(id, (int __user *)arg)) { |
372 | err = -EFAULT; |
373 | break; |
374 | } |
375 | dev = get_mdevice(id); |
376 | if (dev) { |
377 | struct mISDN_devinfo di; |
378 | |
379 | memset(&di, 0, sizeof(di)); |
380 | di.id = dev->id; |
381 | di.Dprotocols = dev->Dprotocols; |
382 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); |
383 | di.protocol = dev->D.protocol; |
384 | memcpy(di.channelmap, dev->channelmap, |
385 | sizeof(di.channelmap)); |
386 | di.nrbchan = dev->nrbchan; |
387 | strscpy(di.name, dev_name(&dev->dev), sizeof(di.name)); |
388 | if (copy_to_user(to: (void __user *)arg, from: &di, n: sizeof(di))) |
389 | err = -EFAULT; |
390 | } else |
391 | err = -ENODEV; |
392 | break; |
393 | default: |
394 | if (sk->sk_state == MISDN_BOUND) |
395 | err = data_sock_ioctl_bound(sk, cmd, |
396 | p: (void __user *)arg); |
397 | else |
398 | err = -ENOTCONN; |
399 | } |
400 | return err; |
401 | } |
402 | |
403 | static int data_sock_setsockopt(struct socket *sock, int level, int optname, |
404 | sockptr_t optval, unsigned int optlen) |
405 | { |
406 | struct sock *sk = sock->sk; |
407 | int err = 0, opt = 0; |
408 | |
409 | if (*debug & DEBUG_SOCKET) |
410 | printk(KERN_DEBUG "%s(%p, %d, %x, optval, %d)\n" , __func__, sock, |
411 | level, optname, optlen); |
412 | |
413 | lock_sock(sk); |
414 | |
415 | switch (optname) { |
416 | case MISDN_TIME_STAMP: |
417 | err = copy_safe_from_sockptr(dst: &opt, ksize: sizeof(opt), |
418 | optval, optlen); |
419 | if (err) |
420 | break; |
421 | |
422 | if (opt) |
423 | _pms(sk)->cmask |= MISDN_TIME_STAMP; |
424 | else |
425 | _pms(sk)->cmask &= ~MISDN_TIME_STAMP; |
426 | break; |
427 | default: |
428 | err = -ENOPROTOOPT; |
429 | break; |
430 | } |
431 | release_sock(sk); |
432 | return err; |
433 | } |
434 | |
435 | static int data_sock_getsockopt(struct socket *sock, int level, int optname, |
436 | char __user *optval, int __user *optlen) |
437 | { |
438 | struct sock *sk = sock->sk; |
439 | int len, opt; |
440 | |
441 | if (get_user(len, optlen)) |
442 | return -EFAULT; |
443 | |
444 | if (len != sizeof(char)) |
445 | return -EINVAL; |
446 | |
447 | switch (optname) { |
448 | case MISDN_TIME_STAMP: |
449 | if (_pms(sk)->cmask & MISDN_TIME_STAMP) |
450 | opt = 1; |
451 | else |
452 | opt = 0; |
453 | |
454 | if (put_user(opt, optval)) |
455 | return -EFAULT; |
456 | break; |
457 | default: |
458 | return -ENOPROTOOPT; |
459 | } |
460 | |
461 | return 0; |
462 | } |
463 | |
464 | static int |
465 | data_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) |
466 | { |
467 | struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr; |
468 | struct sock *sk = sock->sk; |
469 | struct sock *csk; |
470 | int err = 0; |
471 | |
472 | if (*debug & DEBUG_SOCKET) |
473 | printk(KERN_DEBUG "%s(%p) sk=%p\n" , __func__, sock, sk); |
474 | if (addr_len != sizeof(struct sockaddr_mISDN)) |
475 | return -EINVAL; |
476 | if (!maddr || maddr->family != AF_ISDN) |
477 | return -EINVAL; |
478 | |
479 | lock_sock(sk); |
480 | |
481 | if (_pms(sk)->dev) { |
482 | err = -EALREADY; |
483 | goto done; |
484 | } |
485 | _pms(sk)->dev = get_mdevice(maddr->dev); |
486 | if (!_pms(sk)->dev) { |
487 | err = -ENODEV; |
488 | goto done; |
489 | } |
490 | |
491 | if (sk->sk_protocol < ISDN_P_B_START) { |
492 | read_lock_bh(&data_sockets.lock); |
493 | sk_for_each(csk, &data_sockets.head) { |
494 | if (sk == csk) |
495 | continue; |
496 | if (_pms(csk)->dev != _pms(sk)->dev) |
497 | continue; |
498 | if (csk->sk_protocol >= ISDN_P_B_START) |
499 | continue; |
500 | if (IS_ISDN_P_TE(csk->sk_protocol) |
501 | == IS_ISDN_P_TE(sk->sk_protocol)) |
502 | continue; |
503 | read_unlock_bh(&data_sockets.lock); |
504 | err = -EBUSY; |
505 | goto done; |
506 | } |
507 | read_unlock_bh(&data_sockets.lock); |
508 | } |
509 | |
510 | _pms(sk)->ch.send = mISDN_send; |
511 | _pms(sk)->ch.ctrl = mISDN_ctrl; |
512 | |
513 | switch (sk->sk_protocol) { |
514 | case ISDN_P_TE_S0: |
515 | case ISDN_P_NT_S0: |
516 | case ISDN_P_TE_E1: |
517 | case ISDN_P_NT_E1: |
518 | mISDN_sock_unlink(l: &data_sockets, sk); |
519 | err = connect_layer1(_pms(sk)->dev, &_pms(sk)->ch, |
520 | sk->sk_protocol, maddr); |
521 | if (err) |
522 | mISDN_sock_link(l: &data_sockets, sk); |
523 | break; |
524 | case ISDN_P_LAPD_TE: |
525 | case ISDN_P_LAPD_NT: |
526 | err = create_l2entity(_pms(sk)->dev, &_pms(sk)->ch, |
527 | sk->sk_protocol, maddr); |
528 | break; |
529 | case ISDN_P_B_RAW: |
530 | case ISDN_P_B_HDLC: |
531 | case ISDN_P_B_X75SLP: |
532 | case ISDN_P_B_L2DTMF: |
533 | case ISDN_P_B_L2DSP: |
534 | case ISDN_P_B_L2DSPHDLC: |
535 | err = connect_Bstack(_pms(sk)->dev, &_pms(sk)->ch, |
536 | sk->sk_protocol, maddr); |
537 | break; |
538 | default: |
539 | err = -EPROTONOSUPPORT; |
540 | } |
541 | if (err) |
542 | goto done; |
543 | sk->sk_state = MISDN_BOUND; |
544 | _pms(sk)->ch.protocol = sk->sk_protocol; |
545 | |
546 | done: |
547 | release_sock(sk); |
548 | return err; |
549 | } |
550 | |
551 | static int |
552 | data_sock_getname(struct socket *sock, struct sockaddr *addr, |
553 | int peer) |
554 | { |
555 | struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr; |
556 | struct sock *sk = sock->sk; |
557 | |
558 | if (!_pms(sk)->dev) |
559 | return -EBADFD; |
560 | |
561 | lock_sock(sk); |
562 | |
563 | maddr->family = AF_ISDN; |
564 | maddr->dev = _pms(sk)->dev->id; |
565 | maddr->channel = _pms(sk)->ch.nr; |
566 | maddr->sapi = _pms(sk)->ch.addr & 0xff; |
567 | maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xff; |
568 | release_sock(sk); |
569 | return sizeof(*maddr); |
570 | } |
571 | |
572 | static const struct proto_ops data_sock_ops = { |
573 | .family = PF_ISDN, |
574 | .owner = THIS_MODULE, |
575 | .release = data_sock_release, |
576 | .ioctl = data_sock_ioctl, |
577 | .bind = data_sock_bind, |
578 | .getname = data_sock_getname, |
579 | .sendmsg = mISDN_sock_sendmsg, |
580 | .recvmsg = mISDN_sock_recvmsg, |
581 | .poll = datagram_poll, |
582 | .listen = sock_no_listen, |
583 | .shutdown = sock_no_shutdown, |
584 | .setsockopt = data_sock_setsockopt, |
585 | .getsockopt = data_sock_getsockopt, |
586 | .connect = sock_no_connect, |
587 | .socketpair = sock_no_socketpair, |
588 | .accept = sock_no_accept, |
589 | .mmap = sock_no_mmap |
590 | }; |
591 | |
592 | static int |
593 | data_sock_create(struct net *net, struct socket *sock, int protocol, int kern) |
594 | { |
595 | struct sock *sk; |
596 | |
597 | if (sock->type != SOCK_DGRAM) |
598 | return -ESOCKTNOSUPPORT; |
599 | |
600 | sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, prot: &mISDN_proto, kern); |
601 | if (!sk) |
602 | return -ENOMEM; |
603 | |
604 | sock_init_data(sock, sk); |
605 | |
606 | sock->ops = &data_sock_ops; |
607 | sock->state = SS_UNCONNECTED; |
608 | sock_reset_flag(sk, flag: SOCK_ZAPPED); |
609 | |
610 | sk->sk_protocol = protocol; |
611 | sk->sk_state = MISDN_OPEN; |
612 | mISDN_sock_link(l: &data_sockets, sk); |
613 | |
614 | return 0; |
615 | } |
616 | |
617 | static int |
618 | base_sock_release(struct socket *sock) |
619 | { |
620 | struct sock *sk = sock->sk; |
621 | |
622 | printk(KERN_DEBUG "%s(%p) sk=%p\n" , __func__, sock, sk); |
623 | if (!sk) |
624 | return 0; |
625 | |
626 | mISDN_sock_unlink(l: &base_sockets, sk); |
627 | sock_orphan(sk); |
628 | sock_put(sk); |
629 | |
630 | return 0; |
631 | } |
632 | |
633 | static int |
634 | base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
635 | { |
636 | int err = 0, id; |
637 | struct mISDNdevice *dev; |
638 | struct mISDNversion ver; |
639 | |
640 | switch (cmd) { |
641 | case IMGETVERSION: |
642 | ver.major = MISDN_MAJOR_VERSION; |
643 | ver.minor = MISDN_MINOR_VERSION; |
644 | ver.release = MISDN_RELEASE; |
645 | if (copy_to_user(to: (void __user *)arg, from: &ver, n: sizeof(ver))) |
646 | err = -EFAULT; |
647 | break; |
648 | case IMGETCOUNT: |
649 | id = get_mdevice_count(); |
650 | if (put_user(id, (int __user *)arg)) |
651 | err = -EFAULT; |
652 | break; |
653 | case IMGETDEVINFO: |
654 | if (get_user(id, (int __user *)arg)) { |
655 | err = -EFAULT; |
656 | break; |
657 | } |
658 | dev = get_mdevice(id); |
659 | if (dev) { |
660 | struct mISDN_devinfo di; |
661 | |
662 | memset(&di, 0, sizeof(di)); |
663 | di.id = dev->id; |
664 | di.Dprotocols = dev->Dprotocols; |
665 | di.Bprotocols = dev->Bprotocols | get_all_Bprotocols(); |
666 | di.protocol = dev->D.protocol; |
667 | memcpy(di.channelmap, dev->channelmap, |
668 | sizeof(di.channelmap)); |
669 | di.nrbchan = dev->nrbchan; |
670 | strscpy(di.name, dev_name(&dev->dev), sizeof(di.name)); |
671 | if (copy_to_user(to: (void __user *)arg, from: &di, n: sizeof(di))) |
672 | err = -EFAULT; |
673 | } else |
674 | err = -ENODEV; |
675 | break; |
676 | case IMSETDEVNAME: |
677 | { |
678 | struct mISDN_devrename dn; |
679 | if (copy_from_user(to: &dn, from: (void __user *)arg, |
680 | n: sizeof(dn))) { |
681 | err = -EFAULT; |
682 | break; |
683 | } |
684 | dn.name[sizeof(dn.name) - 1] = '\0'; |
685 | dev = get_mdevice(dn.id); |
686 | if (dev) |
687 | err = device_rename(dev: &dev->dev, new_name: dn.name); |
688 | else |
689 | err = -ENODEV; |
690 | } |
691 | break; |
692 | default: |
693 | err = -EINVAL; |
694 | } |
695 | return err; |
696 | } |
697 | |
698 | static int |
699 | base_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_len) |
700 | { |
701 | struct sockaddr_mISDN *maddr = (struct sockaddr_mISDN *) addr; |
702 | struct sock *sk = sock->sk; |
703 | int err = 0; |
704 | |
705 | if (addr_len < sizeof(struct sockaddr_mISDN)) |
706 | return -EINVAL; |
707 | |
708 | if (!maddr || maddr->family != AF_ISDN) |
709 | return -EINVAL; |
710 | |
711 | lock_sock(sk); |
712 | |
713 | if (_pms(sk)->dev) { |
714 | err = -EALREADY; |
715 | goto done; |
716 | } |
717 | |
718 | _pms(sk)->dev = get_mdevice(maddr->dev); |
719 | if (!_pms(sk)->dev) { |
720 | err = -ENODEV; |
721 | goto done; |
722 | } |
723 | sk->sk_state = MISDN_BOUND; |
724 | |
725 | done: |
726 | release_sock(sk); |
727 | return err; |
728 | } |
729 | |
730 | static const struct proto_ops base_sock_ops = { |
731 | .family = PF_ISDN, |
732 | .owner = THIS_MODULE, |
733 | .release = base_sock_release, |
734 | .ioctl = base_sock_ioctl, |
735 | .bind = base_sock_bind, |
736 | .getname = sock_no_getname, |
737 | .sendmsg = sock_no_sendmsg, |
738 | .recvmsg = sock_no_recvmsg, |
739 | .listen = sock_no_listen, |
740 | .shutdown = sock_no_shutdown, |
741 | .connect = sock_no_connect, |
742 | .socketpair = sock_no_socketpair, |
743 | .accept = sock_no_accept, |
744 | .mmap = sock_no_mmap |
745 | }; |
746 | |
747 | |
748 | static int |
749 | base_sock_create(struct net *net, struct socket *sock, int protocol, int kern) |
750 | { |
751 | struct sock *sk; |
752 | |
753 | if (sock->type != SOCK_RAW) |
754 | return -ESOCKTNOSUPPORT; |
755 | if (!capable(CAP_NET_RAW)) |
756 | return -EPERM; |
757 | |
758 | sk = sk_alloc(net, PF_ISDN, GFP_KERNEL, prot: &mISDN_proto, kern); |
759 | if (!sk) |
760 | return -ENOMEM; |
761 | |
762 | sock_init_data(sock, sk); |
763 | sock->ops = &base_sock_ops; |
764 | sock->state = SS_UNCONNECTED; |
765 | sock_reset_flag(sk, flag: SOCK_ZAPPED); |
766 | sk->sk_protocol = protocol; |
767 | sk->sk_state = MISDN_OPEN; |
768 | mISDN_sock_link(l: &base_sockets, sk); |
769 | |
770 | return 0; |
771 | } |
772 | |
773 | static int |
774 | mISDN_sock_create(struct net *net, struct socket *sock, int proto, int kern) |
775 | { |
776 | int err = -EPROTONOSUPPORT; |
777 | |
778 | switch (proto) { |
779 | case ISDN_P_BASE: |
780 | err = base_sock_create(net, sock, protocol: proto, kern); |
781 | break; |
782 | case ISDN_P_TE_S0: |
783 | case ISDN_P_NT_S0: |
784 | case ISDN_P_TE_E1: |
785 | case ISDN_P_NT_E1: |
786 | case ISDN_P_LAPD_TE: |
787 | case ISDN_P_LAPD_NT: |
788 | case ISDN_P_B_RAW: |
789 | case ISDN_P_B_HDLC: |
790 | case ISDN_P_B_X75SLP: |
791 | case ISDN_P_B_L2DTMF: |
792 | case ISDN_P_B_L2DSP: |
793 | case ISDN_P_B_L2DSPHDLC: |
794 | err = data_sock_create(net, sock, protocol: proto, kern); |
795 | break; |
796 | default: |
797 | return err; |
798 | } |
799 | |
800 | return err; |
801 | } |
802 | |
803 | static const struct net_proto_family mISDN_sock_family_ops = { |
804 | .owner = THIS_MODULE, |
805 | .family = PF_ISDN, |
806 | .create = mISDN_sock_create, |
807 | }; |
808 | |
809 | int |
810 | misdn_sock_init(u_int *deb) |
811 | { |
812 | int err; |
813 | |
814 | debug = deb; |
815 | err = sock_register(fam: &mISDN_sock_family_ops); |
816 | if (err) |
817 | printk(KERN_ERR "%s: error(%d)\n" , __func__, err); |
818 | return err; |
819 | } |
820 | |
821 | void |
822 | misdn_sock_cleanup(void) |
823 | { |
824 | sock_unregister(PF_ISDN); |
825 | } |
826 | |