1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include <linux/compiler.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/rtnetlink.h>
27#include <linux/init.h>
28#include <linux/slab.h>
29#include <linux/sched/signal.h>
30
31#include <net/llc.h>
32#include <net/llc_sap.h>
33#include <net/llc_pdu.h>
34#include <net/llc_conn.h>
35#include <net/tcp_states.h>
36
37
38static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
39static u16 llc_ui_sap_link_no_max[256];
40static struct sockaddr_llc llc_ui_addrnull;
41static const struct proto_ops llc_ui_ops;
42
43static bool llc_ui_wait_for_conn(struct sock *sk, long timeout);
44static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
45static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
46
47#if 0
48#define dprintk(args...) printk(KERN_DEBUG args)
49#else
50#define dprintk(args...)
51#endif
52
53
54#define LLC_CMSG_PKTINFO 1
55
56
57
58
59
60
61
62
63static inline u16 llc_ui_next_link_no(int sap)
64{
65 return llc_ui_sap_link_no_max[sap]++;
66}
67
68
69
70
71
72
73
74static inline __be16 llc_proto_type(u16 arphrd)
75{
76 return htons(ETH_P_802_2);
77}
78
79
80
81
82
83static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr)
84{
85 return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr));
86}
87
88
89
90
91
92
93
94
95
96
97static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr)
98{
99 u8 rc = LLC_PDU_LEN_U;
100
101 if (addr->sllc_test || addr->sllc_xid)
102 rc = LLC_PDU_LEN_U;
103 else if (sk->sk_type == SOCK_STREAM)
104 rc = LLC_PDU_LEN_I;
105 return rc;
106}
107
108
109
110
111
112
113
114
115
116
117
118
119static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
120{
121 struct llc_sock* llc = llc_sk(sk);
122
123 if (unlikely(llc_data_accept_state(llc->state) ||
124 llc->remote_busy_flag ||
125 llc->p_flag)) {
126 long timeout = sock_sndtimeo(sk, noblock);
127 int rc;
128
129 rc = llc_ui_wait_for_busy_core(sk, timeout);
130 if (rc) {
131 kfree_skb(skb);
132 return rc;
133 }
134 }
135 return llc_build_and_send_pkt(sk, skb);
136}
137
138static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
139{
140 sock_graft(sk, sock);
141 sk->sk_type = sock->type;
142 sock->ops = &llc_ui_ops;
143}
144
145static struct proto llc_proto = {
146 .name = "LLC",
147 .owner = THIS_MODULE,
148 .obj_size = sizeof(struct llc_sock),
149 .slab_flags = SLAB_TYPESAFE_BY_RCU,
150};
151
152
153
154
155
156
157
158
159
160
161
162
163static int llc_ui_create(struct net *net, struct socket *sock, int protocol,
164 int kern)
165{
166 struct sock *sk;
167 int rc = -ESOCKTNOSUPPORT;
168
169 if (!ns_capable(net->user_ns, CAP_NET_RAW))
170 return -EPERM;
171
172 if (!net_eq(net, &init_net))
173 return -EAFNOSUPPORT;
174
175 if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
176 rc = -ENOMEM;
177 sk = llc_sk_alloc(net, PF_LLC, GFP_KERNEL, &llc_proto, kern);
178 if (sk) {
179 rc = 0;
180 llc_ui_sk_init(sock, sk);
181 }
182 }
183 return rc;
184}
185
186
187
188
189
190
191
192static int llc_ui_release(struct socket *sock)
193{
194 struct sock *sk = sock->sk;
195 struct llc_sock *llc;
196
197 if (unlikely(sk == NULL))
198 goto out;
199 sock_hold(sk);
200 lock_sock(sk);
201 llc = llc_sk(sk);
202 dprintk("%s: closing local(%02X) remote(%02X)\n", __func__,
203 llc->laddr.lsap, llc->daddr.lsap);
204 if (!llc_send_disc(sk))
205 llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
206 if (!sock_flag(sk, SOCK_ZAPPED)) {
207 struct llc_sap *sap = llc->sap;
208
209
210
211
212 llc_sap_hold(sap);
213 llc_sap_remove_socket(llc->sap, sk);
214 release_sock(sk);
215 llc_sap_put(sap);
216 } else {
217 release_sock(sk);
218 }
219 if (llc->dev)
220 dev_put(llc->dev);
221 sock_put(sk);
222 llc_sk_free(sk);
223out:
224 return 0;
225}
226
227
228
229
230
231
232
233
234static int llc_ui_autoport(void)
235{
236 struct llc_sap *sap;
237 int i, tries = 0;
238
239 while (tries < LLC_SAP_DYN_TRIES) {
240 for (i = llc_ui_sap_last_autoport;
241 i < LLC_SAP_DYN_STOP; i += 2) {
242 sap = llc_sap_find(i);
243 if (!sap) {
244 llc_ui_sap_last_autoport = i + 2;
245 goto out;
246 }
247 llc_sap_put(sap);
248 }
249 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
250 tries++;
251 }
252 i = 0;
253out:
254 return i;
255}
256
257
258
259
260
261
262
263
264
265
266
267static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
268{
269 struct sock *sk = sock->sk;
270 struct llc_sock *llc = llc_sk(sk);
271 struct llc_sap *sap;
272 int rc = -EINVAL;
273
274 if (!sock_flag(sk, SOCK_ZAPPED))
275 goto out;
276 rc = -ENODEV;
277 if (sk->sk_bound_dev_if) {
278 llc->dev = dev_get_by_index(&init_net, sk->sk_bound_dev_if);
279 if (llc->dev && addr->sllc_arphrd != llc->dev->type) {
280 dev_put(llc->dev);
281 llc->dev = NULL;
282 }
283 } else
284 llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
285 if (!llc->dev)
286 goto out;
287 rc = -EUSERS;
288 llc->laddr.lsap = llc_ui_autoport();
289 if (!llc->laddr.lsap)
290 goto out;
291 rc = -EBUSY;
292 sap = llc_sap_open(llc->laddr.lsap, NULL);
293 if (!sap)
294 goto out;
295 memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
296 memcpy(&llc->addr, addr, sizeof(llc->addr));
297
298 llc_sap_add_socket(sap, sk);
299 sock_reset_flag(sk, SOCK_ZAPPED);
300 rc = 0;
301out:
302 return rc;
303}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
320{
321 struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
322 struct sock *sk = sock->sk;
323 struct llc_sock *llc = llc_sk(sk);
324 struct llc_sap *sap;
325 int rc = -EINVAL;
326
327 dprintk("%s: binding %02X\n", __func__, addr->sllc_sap);
328
329 lock_sock(sk);
330 if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
331 goto out;
332 rc = -EAFNOSUPPORT;
333 if (unlikely(addr->sllc_family != AF_LLC))
334 goto out;
335 rc = -ENODEV;
336 rcu_read_lock();
337 if (sk->sk_bound_dev_if) {
338 llc->dev = dev_get_by_index_rcu(&init_net, sk->sk_bound_dev_if);
339 if (llc->dev) {
340 if (!addr->sllc_arphrd)
341 addr->sllc_arphrd = llc->dev->type;
342 if (is_zero_ether_addr(addr->sllc_mac))
343 memcpy(addr->sllc_mac, llc->dev->dev_addr,
344 IFHWADDRLEN);
345 if (addr->sllc_arphrd != llc->dev->type ||
346 !ether_addr_equal(addr->sllc_mac,
347 llc->dev->dev_addr)) {
348 rc = -EINVAL;
349 llc->dev = NULL;
350 }
351 }
352 } else
353 llc->dev = dev_getbyhwaddr_rcu(&init_net, addr->sllc_arphrd,
354 addr->sllc_mac);
355 if (llc->dev)
356 dev_hold(llc->dev);
357 rcu_read_unlock();
358 if (!llc->dev)
359 goto out;
360 if (!addr->sllc_sap) {
361 rc = -EUSERS;
362 addr->sllc_sap = llc_ui_autoport();
363 if (!addr->sllc_sap)
364 goto out;
365 }
366 sap = llc_sap_find(addr->sllc_sap);
367 if (!sap) {
368 sap = llc_sap_open(addr->sllc_sap, NULL);
369 rc = -EBUSY;
370 if (!sap)
371 goto out;
372 } else {
373 struct llc_addr laddr, daddr;
374 struct sock *ask;
375
376 memset(&laddr, 0, sizeof(laddr));
377 memset(&daddr, 0, sizeof(daddr));
378
379
380
381
382 memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
383 laddr.lsap = addr->sllc_sap;
384 rc = -EADDRINUSE;
385 ask = llc_lookup_established(sap, &daddr, &laddr);
386 if (ask) {
387 sock_put(ask);
388 goto out_put;
389 }
390 }
391 llc->laddr.lsap = addr->sllc_sap;
392 memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
393 memcpy(&llc->addr, addr, sizeof(llc->addr));
394
395 llc_sap_add_socket(sap, sk);
396 sock_reset_flag(sk, SOCK_ZAPPED);
397 rc = 0;
398out_put:
399 llc_sap_put(sap);
400out:
401 release_sock(sk);
402 return rc;
403}
404
405
406
407
408
409
410
411
412
413
414
415
416static int llc_ui_shutdown(struct socket *sock, int how)
417{
418 struct sock *sk = sock->sk;
419 int rc = -ENOTCONN;
420
421 lock_sock(sk);
422 if (unlikely(sk->sk_state != TCP_ESTABLISHED))
423 goto out;
424 rc = -EINVAL;
425 if (how != 2)
426 goto out;
427 rc = llc_send_disc(sk);
428 if (!rc)
429 rc = llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
430
431 sk->sk_state_change(sk);
432out:
433 release_sock(sk);
434 return rc;
435}
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
452 int addrlen, int flags)
453{
454 struct sock *sk = sock->sk;
455 struct llc_sock *llc = llc_sk(sk);
456 struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
457 int rc = -EINVAL;
458
459 lock_sock(sk);
460 if (unlikely(addrlen != sizeof(*addr)))
461 goto out;
462 rc = -EAFNOSUPPORT;
463 if (unlikely(addr->sllc_family != AF_LLC))
464 goto out;
465 if (unlikely(sk->sk_type != SOCK_STREAM))
466 goto out;
467 rc = -EALREADY;
468 if (unlikely(sock->state == SS_CONNECTING))
469 goto out;
470
471 if (sock_flag(sk, SOCK_ZAPPED)) {
472
473 rc = llc_ui_autobind(sock, addr);
474 if (rc)
475 goto out;
476 }
477 llc->daddr.lsap = addr->sllc_sap;
478 memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
479 sock->state = SS_CONNECTING;
480 sk->sk_state = TCP_SYN_SENT;
481 llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);
482 rc = llc_establish_connection(sk, llc->dev->dev_addr,
483 addr->sllc_mac, addr->sllc_sap);
484 if (rc) {
485 dprintk("%s: llc_ui_send_conn failed :-(\n", __func__);
486 sock->state = SS_UNCONNECTED;
487 sk->sk_state = TCP_CLOSE;
488 goto out;
489 }
490
491 if (sk->sk_state == TCP_SYN_SENT) {
492 const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
493
494 if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
495 goto out;
496
497 rc = sock_intr_errno(timeo);
498 if (signal_pending(current))
499 goto out;
500 }
501
502 if (sk->sk_state == TCP_CLOSE)
503 goto sock_error;
504
505 sock->state = SS_CONNECTED;
506 rc = 0;
507out:
508 release_sock(sk);
509 return rc;
510sock_error:
511 rc = sock_error(sk) ? : -ECONNABORTED;
512 sock->state = SS_UNCONNECTED;
513 goto out;
514}
515
516
517
518
519
520
521
522
523
524static int llc_ui_listen(struct socket *sock, int backlog)
525{
526 struct sock *sk = sock->sk;
527 int rc = -EINVAL;
528
529 lock_sock(sk);
530 if (unlikely(sock->state != SS_UNCONNECTED))
531 goto out;
532 rc = -EOPNOTSUPP;
533 if (unlikely(sk->sk_type != SOCK_STREAM))
534 goto out;
535 rc = -EAGAIN;
536 if (sock_flag(sk, SOCK_ZAPPED))
537 goto out;
538 rc = 0;
539 if (!(unsigned int)backlog)
540 backlog = 1;
541 sk->sk_max_ack_backlog = backlog;
542 if (sk->sk_state != TCP_LISTEN) {
543 sk->sk_ack_backlog = 0;
544 sk->sk_state = TCP_LISTEN;
545 }
546 sk->sk_socket->flags |= __SO_ACCEPTCON;
547out:
548 release_sock(sk);
549 return rc;
550}
551
552static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
553{
554 DEFINE_WAIT_FUNC(wait, woken_wake_function);
555 int rc = 0;
556
557 add_wait_queue(sk_sleep(sk), &wait);
558 while (1) {
559 if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE, &wait))
560 break;
561 rc = -ERESTARTSYS;
562 if (signal_pending(current))
563 break;
564 rc = -EAGAIN;
565 if (!timeout)
566 break;
567 rc = 0;
568 }
569 remove_wait_queue(sk_sleep(sk), &wait);
570 return rc;
571}
572
573static bool llc_ui_wait_for_conn(struct sock *sk, long timeout)
574{
575 DEFINE_WAIT_FUNC(wait, woken_wake_function);
576
577 add_wait_queue(sk_sleep(sk), &wait);
578 while (1) {
579 if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT, &wait))
580 break;
581 if (signal_pending(current) || !timeout)
582 break;
583 }
584 remove_wait_queue(sk_sleep(sk), &wait);
585 return timeout;
586}
587
588static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
589{
590 DEFINE_WAIT_FUNC(wait, woken_wake_function);
591 struct llc_sock *llc = llc_sk(sk);
592 int rc;
593
594 add_wait_queue(sk_sleep(sk), &wait);
595 while (1) {
596 rc = 0;
597 if (sk_wait_event(sk, &timeout,
598 (sk->sk_shutdown & RCV_SHUTDOWN) ||
599 (!llc_data_accept_state(llc->state) &&
600 !llc->remote_busy_flag &&
601 !llc->p_flag), &wait))
602 break;
603 rc = -ERESTARTSYS;
604 if (signal_pending(current))
605 break;
606 rc = -EAGAIN;
607 if (!timeout)
608 break;
609 }
610 remove_wait_queue(sk_sleep(sk), &wait);
611 return rc;
612}
613
614static int llc_wait_data(struct sock *sk, long timeo)
615{
616 int rc;
617
618 while (1) {
619
620
621
622 rc = sock_error(sk);
623 if (rc)
624 break;
625 rc = 0;
626 if (sk->sk_shutdown & RCV_SHUTDOWN)
627 break;
628 rc = -EAGAIN;
629 if (!timeo)
630 break;
631 rc = sock_intr_errno(timeo);
632 if (signal_pending(current))
633 break;
634 rc = 0;
635 if (sk_wait_data(sk, &timeo, NULL))
636 break;
637 }
638 return rc;
639}
640
641static void llc_cmsg_rcv(struct msghdr *msg, struct sk_buff *skb)
642{
643 struct llc_sock *llc = llc_sk(skb->sk);
644
645 if (llc->cmsg_flags & LLC_CMSG_PKTINFO) {
646 struct llc_pktinfo info;
647
648 memset(&info, 0, sizeof(info));
649 info.lpi_ifindex = llc_sk(skb->sk)->dev->ifindex;
650 llc_pdu_decode_dsap(skb, &info.lpi_sap);
651 llc_pdu_decode_da(skb, info.lpi_mac);
652 put_cmsg(msg, SOL_LLC, LLC_OPT_PKTINFO, sizeof(info), &info);
653 }
654}
655
656
657
658
659
660
661
662
663
664
665
666static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags,
667 bool kern)
668{
669 struct sock *sk = sock->sk, *newsk;
670 struct llc_sock *llc, *newllc;
671 struct sk_buff *skb;
672 int rc = -EOPNOTSUPP;
673
674 dprintk("%s: accepting on %02X\n", __func__,
675 llc_sk(sk)->laddr.lsap);
676 lock_sock(sk);
677 if (unlikely(sk->sk_type != SOCK_STREAM))
678 goto out;
679 rc = -EINVAL;
680 if (unlikely(sock->state != SS_UNCONNECTED ||
681 sk->sk_state != TCP_LISTEN))
682 goto out;
683
684 if (skb_queue_empty(&sk->sk_receive_queue)) {
685 rc = llc_wait_data(sk, sk->sk_rcvtimeo);
686 if (rc)
687 goto out;
688 }
689 dprintk("%s: got a new connection on %02X\n", __func__,
690 llc_sk(sk)->laddr.lsap);
691 skb = skb_dequeue(&sk->sk_receive_queue);
692 rc = -EINVAL;
693 if (!skb->sk)
694 goto frees;
695 rc = 0;
696 newsk = skb->sk;
697
698 llc_ui_sk_init(newsock, newsk);
699 sock_reset_flag(newsk, SOCK_ZAPPED);
700 newsk->sk_state = TCP_ESTABLISHED;
701 newsock->state = SS_CONNECTED;
702 llc = llc_sk(sk);
703 newllc = llc_sk(newsk);
704 memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr));
705 newllc->link = llc_ui_next_link_no(newllc->laddr.lsap);
706
707
708 sk->sk_state = TCP_LISTEN;
709 sk_acceptq_removed(sk);
710 dprintk("%s: ok success on %02X, client on %02X\n", __func__,
711 llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
712frees:
713 kfree_skb(skb);
714out:
715 release_sock(sk);
716 return rc;
717}
718
719
720
721
722
723
724
725
726
727
728
729static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
730 int flags)
731{
732 DECLARE_SOCKADDR(struct sockaddr_llc *, uaddr, msg->msg_name);
733 const int nonblock = flags & MSG_DONTWAIT;
734 struct sk_buff *skb = NULL;
735 struct sock *sk = sock->sk;
736 struct llc_sock *llc = llc_sk(sk);
737 size_t copied = 0;
738 u32 peek_seq = 0;
739 u32 *seq, skb_len;
740 unsigned long used;
741 int target;
742 long timeo;
743
744 lock_sock(sk);
745 copied = -ENOTCONN;
746 if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
747 goto out;
748
749 timeo = sock_rcvtimeo(sk, nonblock);
750
751 seq = &llc->copied_seq;
752 if (flags & MSG_PEEK) {
753 peek_seq = llc->copied_seq;
754 seq = &peek_seq;
755 }
756
757 target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
758 copied = 0;
759
760 do {
761 u32 offset;
762
763
764
765
766
767
768 if (signal_pending(current)) {
769 if (copied)
770 break;
771 copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
772 break;
773 }
774
775
776
777 skb = skb_peek(&sk->sk_receive_queue);
778 if (skb) {
779 offset = *seq;
780 goto found_ok_skb;
781 }
782
783
784 if (copied >= target && !sk->sk_backlog.tail)
785 break;
786
787 if (copied) {
788 if (sk->sk_err ||
789 sk->sk_state == TCP_CLOSE ||
790 (sk->sk_shutdown & RCV_SHUTDOWN) ||
791 !timeo ||
792 (flags & MSG_PEEK))
793 break;
794 } else {
795 if (sock_flag(sk, SOCK_DONE))
796 break;
797
798 if (sk->sk_err) {
799 copied = sock_error(sk);
800 break;
801 }
802 if (sk->sk_shutdown & RCV_SHUTDOWN)
803 break;
804
805 if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE) {
806 if (!sock_flag(sk, SOCK_DONE)) {
807
808
809
810
811 copied = -ENOTCONN;
812 break;
813 }
814 break;
815 }
816 if (!timeo) {
817 copied = -EAGAIN;
818 break;
819 }
820 }
821
822 if (copied >= target) {
823 release_sock(sk);
824 lock_sock(sk);
825 } else
826 sk_wait_data(sk, &timeo, NULL);
827
828 if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
829 net_dbg_ratelimited("LLC(%s:%d): Application bug, race in MSG_PEEK\n",
830 current->comm,
831 task_pid_nr(current));
832 peek_seq = llc->copied_seq;
833 }
834 continue;
835 found_ok_skb:
836 skb_len = skb->len;
837
838 used = skb->len - offset;
839 if (len < used)
840 used = len;
841
842 if (!(flags & MSG_TRUNC)) {
843 int rc = skb_copy_datagram_msg(skb, offset, msg, used);
844 if (rc) {
845
846 if (!copied)
847 copied = -EFAULT;
848 break;
849 }
850 }
851
852 *seq += used;
853 copied += used;
854 len -= used;
855
856
857 if (sk->sk_type != SOCK_STREAM)
858 goto copy_uaddr;
859
860 if (!(flags & MSG_PEEK)) {
861 skb_unlink(skb, &sk->sk_receive_queue);
862 kfree_skb(skb);
863 *seq = 0;
864 }
865
866
867 if (used + offset < skb_len)
868 continue;
869 } while (len > 0);
870
871out:
872 release_sock(sk);
873 return copied;
874copy_uaddr:
875 if (uaddr != NULL && skb != NULL) {
876 memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
877 msg->msg_namelen = sizeof(*uaddr);
878 }
879 if (llc_sk(sk)->cmsg_flags)
880 llc_cmsg_rcv(msg, skb);
881
882 if (!(flags & MSG_PEEK)) {
883 skb_unlink(skb, &sk->sk_receive_queue);
884 kfree_skb(skb);
885 *seq = 0;
886 }
887
888 goto out;
889}
890
891
892
893
894
895
896
897
898
899
900static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
901{
902 struct sock *sk = sock->sk;
903 struct llc_sock *llc = llc_sk(sk);
904 DECLARE_SOCKADDR(struct sockaddr_llc *, addr, msg->msg_name);
905 int flags = msg->msg_flags;
906 int noblock = flags & MSG_DONTWAIT;
907 struct sk_buff *skb = NULL;
908 size_t size = 0;
909 int rc = -EINVAL, copied = 0, hdrlen;
910
911 dprintk("%s: sending from %02X to %02X\n", __func__,
912 llc->laddr.lsap, llc->daddr.lsap);
913 lock_sock(sk);
914 if (addr) {
915 if (msg->msg_namelen < sizeof(*addr))
916 goto out;
917 } else {
918 if (llc_ui_addr_null(&llc->addr))
919 goto out;
920 addr = &llc->addr;
921 }
922
923 if (sock_flag(sk, SOCK_ZAPPED)) {
924
925 rc = llc_ui_autobind(sock, addr);
926 if (rc)
927 goto out;
928 }
929 hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
930 size = hdrlen + len;
931 if (size > llc->dev->mtu)
932 size = llc->dev->mtu;
933 copied = size - hdrlen;
934 rc = -EINVAL;
935 if (copied < 0)
936 goto out;
937 release_sock(sk);
938 skb = sock_alloc_send_skb(sk, size, noblock, &rc);
939 lock_sock(sk);
940 if (!skb)
941 goto out;
942 skb->dev = llc->dev;
943 skb->protocol = llc_proto_type(addr->sllc_arphrd);
944 skb_reserve(skb, hdrlen);
945 rc = memcpy_from_msg(skb_put(skb, copied), msg, copied);
946 if (rc)
947 goto out;
948 if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) {
949 llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac,
950 addr->sllc_sap);
951 skb = NULL;
952 goto out;
953 }
954 if (addr->sllc_test) {
955 llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac,
956 addr->sllc_sap);
957 skb = NULL;
958 goto out;
959 }
960 if (addr->sllc_xid) {
961 llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac,
962 addr->sllc_sap);
963 skb = NULL;
964 goto out;
965 }
966 rc = -ENOPROTOOPT;
967 if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
968 goto out;
969 rc = llc_ui_send_data(sk, skb, noblock);
970 skb = NULL;
971out:
972 kfree_skb(skb);
973 if (rc)
974 dprintk("%s: failed sending from %02X to %02X: %d\n",
975 __func__, llc->laddr.lsap, llc->daddr.lsap, rc);
976 release_sock(sk);
977 return rc ? : copied;
978}
979
980
981
982
983
984
985
986
987
988
989static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
990 int peer)
991{
992 struct sockaddr_llc sllc;
993 struct sock *sk = sock->sk;
994 struct llc_sock *llc = llc_sk(sk);
995 int rc = -EBADF;
996
997 memset(&sllc, 0, sizeof(sllc));
998 lock_sock(sk);
999 if (sock_flag(sk, SOCK_ZAPPED))
1000 goto out;
1001 if (peer) {
1002 rc = -ENOTCONN;
1003 if (sk->sk_state != TCP_ESTABLISHED)
1004 goto out;
1005 if(llc->dev)
1006 sllc.sllc_arphrd = llc->dev->type;
1007 sllc.sllc_sap = llc->daddr.lsap;
1008 memcpy(&sllc.sllc_mac, &llc->daddr.mac, IFHWADDRLEN);
1009 } else {
1010 rc = -EINVAL;
1011 if (!llc->sap)
1012 goto out;
1013 sllc.sllc_sap = llc->sap->laddr.lsap;
1014
1015 if (llc->dev) {
1016 sllc.sllc_arphrd = llc->dev->type;
1017 memcpy(&sllc.sllc_mac, llc->dev->dev_addr,
1018 IFHWADDRLEN);
1019 }
1020 }
1021 sllc.sllc_family = AF_LLC;
1022 memcpy(uaddr, &sllc, sizeof(sllc));
1023 rc = sizeof(sllc);
1024out:
1025 release_sock(sk);
1026 return rc;
1027}
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037static int llc_ui_ioctl(struct socket *sock, unsigned int cmd,
1038 unsigned long arg)
1039{
1040 return -ENOIOCTLCMD;
1041}
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
1054 char __user *optval, unsigned int optlen)
1055{
1056 struct sock *sk = sock->sk;
1057 struct llc_sock *llc = llc_sk(sk);
1058 unsigned int opt;
1059 int rc = -EINVAL;
1060
1061 lock_sock(sk);
1062 if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
1063 goto out;
1064 rc = get_user(opt, (int __user *)optval);
1065 if (rc)
1066 goto out;
1067 rc = -EINVAL;
1068 switch (optname) {
1069 case LLC_OPT_RETRY:
1070 if (opt > LLC_OPT_MAX_RETRY)
1071 goto out;
1072 llc->n2 = opt;
1073 break;
1074 case LLC_OPT_SIZE:
1075 if (opt > LLC_OPT_MAX_SIZE)
1076 goto out;
1077 llc->n1 = opt;
1078 break;
1079 case LLC_OPT_ACK_TMR_EXP:
1080 if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
1081 goto out;
1082 llc->ack_timer.expire = opt * HZ;
1083 break;
1084 case LLC_OPT_P_TMR_EXP:
1085 if (opt > LLC_OPT_MAX_P_TMR_EXP)
1086 goto out;
1087 llc->pf_cycle_timer.expire = opt * HZ;
1088 break;
1089 case LLC_OPT_REJ_TMR_EXP:
1090 if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
1091 goto out;
1092 llc->rej_sent_timer.expire = opt * HZ;
1093 break;
1094 case LLC_OPT_BUSY_TMR_EXP:
1095 if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
1096 goto out;
1097 llc->busy_state_timer.expire = opt * HZ;
1098 break;
1099 case LLC_OPT_TX_WIN:
1100 if (opt > LLC_OPT_MAX_WIN)
1101 goto out;
1102 llc->k = opt;
1103 break;
1104 case LLC_OPT_RX_WIN:
1105 if (opt > LLC_OPT_MAX_WIN)
1106 goto out;
1107 llc->rw = opt;
1108 break;
1109 case LLC_OPT_PKTINFO:
1110 if (opt)
1111 llc->cmsg_flags |= LLC_CMSG_PKTINFO;
1112 else
1113 llc->cmsg_flags &= ~LLC_CMSG_PKTINFO;
1114 break;
1115 default:
1116 rc = -ENOPROTOOPT;
1117 goto out;
1118 }
1119 rc = 0;
1120out:
1121 release_sock(sk);
1122 return rc;
1123}
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
1136 char __user *optval, int __user *optlen)
1137{
1138 struct sock *sk = sock->sk;
1139 struct llc_sock *llc = llc_sk(sk);
1140 int val = 0, len = 0, rc = -EINVAL;
1141
1142 lock_sock(sk);
1143 if (unlikely(level != SOL_LLC))
1144 goto out;
1145 rc = get_user(len, optlen);
1146 if (rc)
1147 goto out;
1148 rc = -EINVAL;
1149 if (len != sizeof(int))
1150 goto out;
1151 switch (optname) {
1152 case LLC_OPT_RETRY:
1153 val = llc->n2; break;
1154 case LLC_OPT_SIZE:
1155 val = llc->n1; break;
1156 case LLC_OPT_ACK_TMR_EXP:
1157 val = llc->ack_timer.expire / HZ; break;
1158 case LLC_OPT_P_TMR_EXP:
1159 val = llc->pf_cycle_timer.expire / HZ; break;
1160 case LLC_OPT_REJ_TMR_EXP:
1161 val = llc->rej_sent_timer.expire / HZ; break;
1162 case LLC_OPT_BUSY_TMR_EXP:
1163 val = llc->busy_state_timer.expire / HZ; break;
1164 case LLC_OPT_TX_WIN:
1165 val = llc->k; break;
1166 case LLC_OPT_RX_WIN:
1167 val = llc->rw; break;
1168 case LLC_OPT_PKTINFO:
1169 val = (llc->cmsg_flags & LLC_CMSG_PKTINFO) != 0;
1170 break;
1171 default:
1172 rc = -ENOPROTOOPT;
1173 goto out;
1174 }
1175 rc = 0;
1176 if (put_user(len, optlen) || copy_to_user(optval, &val, len))
1177 rc = -EFAULT;
1178out:
1179 release_sock(sk);
1180 return rc;
1181}
1182
1183static const struct net_proto_family llc_ui_family_ops = {
1184 .family = PF_LLC,
1185 .create = llc_ui_create,
1186 .owner = THIS_MODULE,
1187};
1188
1189static const struct proto_ops llc_ui_ops = {
1190 .family = PF_LLC,
1191 .owner = THIS_MODULE,
1192 .release = llc_ui_release,
1193 .bind = llc_ui_bind,
1194 .connect = llc_ui_connect,
1195 .socketpair = sock_no_socketpair,
1196 .accept = llc_ui_accept,
1197 .getname = llc_ui_getname,
1198 .poll = datagram_poll,
1199 .ioctl = llc_ui_ioctl,
1200 .listen = llc_ui_listen,
1201 .shutdown = llc_ui_shutdown,
1202 .setsockopt = llc_ui_setsockopt,
1203 .getsockopt = llc_ui_getsockopt,
1204 .sendmsg = llc_ui_sendmsg,
1205 .recvmsg = llc_ui_recvmsg,
1206 .mmap = sock_no_mmap,
1207 .sendpage = sock_no_sendpage,
1208};
1209
1210static const char llc_proc_err_msg[] __initconst =
1211 KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
1212static const char llc_sysctl_err_msg[] __initconst =
1213 KERN_CRIT "LLC: Unable to register the sysctl entries\n";
1214static const char llc_sock_err_msg[] __initconst =
1215 KERN_CRIT "LLC: Unable to register the network family\n";
1216
1217static int __init llc2_init(void)
1218{
1219 int rc = proto_register(&llc_proto, 0);
1220
1221 if (rc != 0)
1222 goto out;
1223
1224 llc_build_offset_table();
1225 llc_station_init();
1226 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
1227 rc = llc_proc_init();
1228 if (rc != 0) {
1229 printk(llc_proc_err_msg);
1230 goto out_station;
1231 }
1232 rc = llc_sysctl_init();
1233 if (rc) {
1234 printk(llc_sysctl_err_msg);
1235 goto out_proc;
1236 }
1237 rc = sock_register(&llc_ui_family_ops);
1238 if (rc) {
1239 printk(llc_sock_err_msg);
1240 goto out_sysctl;
1241 }
1242 llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
1243 llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
1244out:
1245 return rc;
1246out_sysctl:
1247 llc_sysctl_exit();
1248out_proc:
1249 llc_proc_exit();
1250out_station:
1251 llc_station_exit();
1252 proto_unregister(&llc_proto);
1253 goto out;
1254}
1255
1256static void __exit llc2_exit(void)
1257{
1258 llc_station_exit();
1259 llc_remove_pack(LLC_DEST_SAP);
1260 llc_remove_pack(LLC_DEST_CONN);
1261 sock_unregister(PF_LLC);
1262 llc_proc_exit();
1263 llc_sysctl_exit();
1264 proto_unregister(&llc_proto);
1265}
1266
1267module_init(llc2_init);
1268module_exit(llc2_exit);
1269
1270MODULE_LICENSE("GPL");
1271MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
1272MODULE_DESCRIPTION("IEEE 802.2 PF_LLC support");
1273MODULE_ALIAS_NETPROTO(PF_LLC);
1274