OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [llc/] [af_llc.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * af_llc.c - LLC User Interface SAPs
3
 * Description:
4
 *   Functions in this module are implementation of socket based llc
5
 *   communications for the Linux operating system. Support of llc class
6
 *   one and class two is provided via SOCK_DGRAM and SOCK_STREAM
7
 *   respectively.
8
 *
9
 *   An llc2 connection is (mac + sap), only one llc2 sap connection
10
 *   is allowed per mac. Though one sap may have multiple mac + sap
11
 *   connections.
12
 *
13
 * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
14
 *               2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
15
 *
16
 * This program can be redistributed or modified under the terms of the
17
 * GNU General Public License as published by the Free Software Foundation.
18
 * This program is distributed without any warranty or implied warranty
19
 * of merchantability or fitness for a particular purpose.
20
 *
21
 * See the GNU General Public License for more details.
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 <net/llc.h>
29
#include <net/llc_sap.h>
30
#include <net/llc_pdu.h>
31
#include <net/llc_conn.h>
32
#include <net/tcp_states.h>
33
 
34
/* remember: uninitialized global data is zeroed because its in .bss */
35
static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
36
static u16 llc_ui_sap_link_no_max[256];
37
static struct sockaddr_llc llc_ui_addrnull;
38
static const struct proto_ops llc_ui_ops;
39
 
40
static int llc_ui_wait_for_conn(struct sock *sk, long timeout);
41
static int llc_ui_wait_for_disc(struct sock *sk, long timeout);
42
static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout);
43
 
44
#if 0
45
#define dprintk(args...) printk(KERN_DEBUG args)
46
#else
47
#define dprintk(args...)
48
#endif
49
 
50
/**
51
 *      llc_ui_next_link_no - return the next unused link number for a sap
52
 *      @sap: Address of sap to get link number from.
53
 *
54
 *      Return the next unused link number for a given sap.
55
 */
56
static inline u16 llc_ui_next_link_no(int sap)
57
{
58
        return llc_ui_sap_link_no_max[sap]++;
59
}
60
 
61
/**
62
 *      llc_proto_type - return eth protocol for ARP header type
63
 *      @arphrd: ARP header type.
64
 *
65
 *      Given an ARP header type return the corresponding ethernet protocol.
66
 */
67
static inline __be16 llc_proto_type(u16 arphrd)
68
{
69
        return arphrd == ARPHRD_IEEE802_TR ?
70
                         htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
71
}
72
 
73
/**
74
 *      llc_ui_addr_null - determines if a address structure is null
75
 *      @addr: Address to test if null.
76
 */
77
static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr)
78
{
79
        return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr));
80
}
81
 
82
/**
83
 *      llc_ui_header_len - return length of llc header based on operation
84
 *      @sk: Socket which contains a valid llc socket type.
85
 *      @addr: Complete sockaddr_llc structure received from the user.
86
 *
87
 *      Provide the length of the llc header depending on what kind of
88
 *      operation the user would like to perform and the type of socket.
89
 *      Returns the correct llc header length.
90
 */
91
static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr)
92
{
93
        u8 rc = LLC_PDU_LEN_U;
94
 
95
        if (addr->sllc_test || addr->sllc_xid)
96
                rc = LLC_PDU_LEN_U;
97
        else if (sk->sk_type == SOCK_STREAM)
98
                rc = LLC_PDU_LEN_I;
99
        return rc;
100
}
101
 
102
/**
103
 *      llc_ui_send_data - send data via reliable llc2 connection
104
 *      @sk: Connection the socket is using.
105
 *      @skb: Data the user wishes to send.
106
 *      @addr: Source and destination fields provided by the user.
107
 *      @noblock: can we block waiting for data?
108
 *
109
 *      Send data via reliable llc2 connection.
110
 *      Returns 0 upon success, non-zero if action did not succeed.
111
 */
112
static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
113
{
114
        struct llc_sock* llc = llc_sk(sk);
115
        int rc = 0;
116
 
117
        if (unlikely(llc_data_accept_state(llc->state) ||
118
                     llc->remote_busy_flag ||
119
                     llc->p_flag)) {
120
                long timeout = sock_sndtimeo(sk, noblock);
121
 
122
                rc = llc_ui_wait_for_busy_core(sk, timeout);
123
        }
124
        if (unlikely(!rc))
125
                rc = llc_build_and_send_pkt(sk, skb);
126
        return rc;
127
}
128
 
129
static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
130
{
131
        sk->sk_type     = sock->type;
132
        sk->sk_sleep    = &sock->wait;
133
        sk->sk_socket   = sock;
134
        sock->sk        = sk;
135
        sock->ops       = &llc_ui_ops;
136
}
137
 
138
static struct proto llc_proto = {
139
        .name     = "LLC",
140
        .owner    = THIS_MODULE,
141
        .obj_size = sizeof(struct llc_sock),
142
};
143
 
144
/**
145
 *      llc_ui_create - alloc and init a new llc_ui socket
146
 *      @sock: Socket to initialize and attach allocated sk to.
147
 *      @protocol: Unused.
148
 *
149
 *      Allocate and initialize a new llc_ui socket, validate the user wants a
150
 *      socket type we have available.
151
 *      Returns 0 upon success, negative upon failure.
152
 */
153
static int llc_ui_create(struct net *net, struct socket *sock, int protocol)
154
{
155
        struct sock *sk;
156
        int rc = -ESOCKTNOSUPPORT;
157
 
158
        if (net != &init_net)
159
                return -EAFNOSUPPORT;
160
 
161
        if (likely(sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM)) {
162
                rc = -ENOMEM;
163
                sk = llc_sk_alloc(net, PF_LLC, GFP_KERNEL, &llc_proto);
164
                if (sk) {
165
                        rc = 0;
166
                        llc_ui_sk_init(sock, sk);
167
                }
168
        }
169
        return rc;
170
}
171
 
172
/**
173
 *      llc_ui_release - shutdown socket
174
 *      @sock: Socket to release.
175
 *
176
 *      Shutdown and deallocate an existing socket.
177
 */
178
static int llc_ui_release(struct socket *sock)
179
{
180
        struct sock *sk = sock->sk;
181
        struct llc_sock *llc;
182
 
183
        if (unlikely(sk == NULL))
184
                goto out;
185
        sock_hold(sk);
186
        lock_sock(sk);
187
        llc = llc_sk(sk);
188
        dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__,
189
                llc->laddr.lsap, llc->daddr.lsap);
190
        if (!llc_send_disc(sk))
191
                llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
192
        if (!sock_flag(sk, SOCK_ZAPPED)) {
193
                llc_sap_put(llc->sap);
194
                llc_sap_remove_socket(llc->sap, sk);
195
        }
196
        release_sock(sk);
197
        if (llc->dev)
198
                dev_put(llc->dev);
199
        sock_put(sk);
200
        llc_sk_free(sk);
201
out:
202
        return 0;
203
}
204
 
205
/**
206
 *      llc_ui_autoport - provide dynamically allocate SAP number
207
 *
208
 *      Provide the caller with a dynamically allocated SAP number according
209
 *      to the rules that are set in this function. Returns: 0, upon failure,
210
 *      SAP number otherwise.
211
 */
212
static int llc_ui_autoport(void)
213
{
214
        struct llc_sap *sap;
215
        int i, tries = 0;
216
 
217
        while (tries < LLC_SAP_DYN_TRIES) {
218
                for (i = llc_ui_sap_last_autoport;
219
                     i < LLC_SAP_DYN_STOP; i += 2) {
220
                        sap = llc_sap_find(i);
221
                        if (!sap) {
222
                                llc_ui_sap_last_autoport = i + 2;
223
                                goto out;
224
                        }
225
                        llc_sap_put(sap);
226
                }
227
                llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
228
                tries++;
229
        }
230
        i = 0;
231
out:
232
        return i;
233
}
234
 
235
/**
236
 *      llc_ui_autobind - automatically bind a socket to a sap
237
 *      @sock: socket to bind
238
 *      @addr: address to connect to
239
 *
240
 *      Used by llc_ui_connect and llc_ui_sendmsg when the user hasn't
241
 *      specifically used llc_ui_bind to bind to an specific address/sap
242
 *
243
 *      Returns: 0 upon success, negative otherwise.
244
 */
245
static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
246
{
247
        struct sock *sk = sock->sk;
248
        struct llc_sock *llc = llc_sk(sk);
249
        struct llc_sap *sap;
250
        int rc = -EINVAL;
251
 
252
        if (!sock_flag(sk, SOCK_ZAPPED))
253
                goto out;
254
        rc = -ENODEV;
255
        llc->dev = dev_getfirstbyhwtype(&init_net, addr->sllc_arphrd);
256
        if (!llc->dev)
257
                goto out;
258
        rc = -EUSERS;
259
        llc->laddr.lsap = llc_ui_autoport();
260
        if (!llc->laddr.lsap)
261
                goto out;
262
        rc = -EBUSY; /* some other network layer is using the sap */
263
        sap = llc_sap_open(llc->laddr.lsap, NULL);
264
        if (!sap)
265
                goto out;
266
        memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
267
        memcpy(&llc->addr, addr, sizeof(llc->addr));
268
        /* assign new connection to its SAP */
269
        llc_sap_add_socket(sap, sk);
270
        sock_reset_flag(sk, SOCK_ZAPPED);
271
        rc = 0;
272
out:
273
        return rc;
274
}
275
 
276
/**
277
 *      llc_ui_bind - bind a socket to a specific address.
278
 *      @sock: Socket to bind an address to.
279
 *      @uaddr: Address the user wants the socket bound to.
280
 *      @addrlen: Length of the uaddr structure.
281
 *
282
 *      Bind a socket to a specific address. For llc a user is able to bind to
283
 *      a specific sap only or mac + sap.
284
 *      If the user desires to bind to a specific mac + sap, it is possible to
285
 *      have multiple sap connections via multiple macs.
286
 *      Bind and autobind for that matter must enforce the correct sap usage
287
 *      otherwise all hell will break loose.
288
 *      Returns: 0 upon success, negative otherwise.
289
 */
290
static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
291
{
292
        struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
293
        struct sock *sk = sock->sk;
294
        struct llc_sock *llc = llc_sk(sk);
295
        struct llc_sap *sap;
296
        int rc = -EINVAL;
297
 
298
        dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
299
        if (unlikely(!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr)))
300
                goto out;
301
        rc = -EAFNOSUPPORT;
302
        if (unlikely(addr->sllc_family != AF_LLC))
303
                goto out;
304
        rc = -ENODEV;
305
        rtnl_lock();
306
        llc->dev = dev_getbyhwaddr(&init_net, addr->sllc_arphrd, addr->sllc_mac);
307
        rtnl_unlock();
308
        if (!llc->dev)
309
                goto out;
310
        if (!addr->sllc_sap) {
311
                rc = -EUSERS;
312
                addr->sllc_sap = llc_ui_autoport();
313
                if (!addr->sllc_sap)
314
                        goto out;
315
        }
316
        sap = llc_sap_find(addr->sllc_sap);
317
        if (!sap) {
318
                sap = llc_sap_open(addr->sllc_sap, NULL);
319
                rc = -EBUSY; /* some other network layer is using the sap */
320
                if (!sap)
321
                        goto out;
322
                llc_sap_hold(sap);
323
        } else {
324
                struct llc_addr laddr, daddr;
325
                struct sock *ask;
326
 
327
                memset(&laddr, 0, sizeof(laddr));
328
                memset(&daddr, 0, sizeof(daddr));
329
                /*
330
                 * FIXME: check if the address is multicast,
331
                 *        only SOCK_DGRAM can do this.
332
                 */
333
                memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
334
                laddr.lsap = addr->sllc_sap;
335
                rc = -EADDRINUSE; /* mac + sap clash. */
336
                ask = llc_lookup_established(sap, &daddr, &laddr);
337
                if (ask) {
338
                        sock_put(ask);
339
                        goto out_put;
340
                }
341
        }
342
        llc->laddr.lsap = addr->sllc_sap;
343
        memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
344
        memcpy(&llc->addr, addr, sizeof(llc->addr));
345
        /* assign new connection to its SAP */
346
        llc_sap_add_socket(sap, sk);
347
        sock_reset_flag(sk, SOCK_ZAPPED);
348
        rc = 0;
349
out_put:
350
        llc_sap_put(sap);
351
out:
352
        return rc;
353
}
354
 
355
/**
356
 *      llc_ui_shutdown - shutdown a connect llc2 socket.
357
 *      @sock: Socket to shutdown.
358
 *      @how: What part of the socket to shutdown.
359
 *
360
 *      Shutdown a connected llc2 socket. Currently this function only supports
361
 *      shutting down both sends and receives (2), we could probably make this
362
 *      function such that a user can shutdown only half the connection but not
363
 *      right now.
364
 *      Returns: 0 upon success, negative otherwise.
365
 */
366
static int llc_ui_shutdown(struct socket *sock, int how)
367
{
368
        struct sock *sk = sock->sk;
369
        int rc = -ENOTCONN;
370
 
371
        lock_sock(sk);
372
        if (unlikely(sk->sk_state != TCP_ESTABLISHED))
373
                goto out;
374
        rc = -EINVAL;
375
        if (how != 2)
376
                goto out;
377
        rc = llc_send_disc(sk);
378
        if (!rc)
379
                rc = llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
380
        /* Wake up anyone sleeping in poll */
381
        sk->sk_state_change(sk);
382
out:
383
        release_sock(sk);
384
        return rc;
385
}
386
 
387
/**
388
 *      llc_ui_connect - Connect to a remote llc2 mac + sap.
389
 *      @sock: Socket which will be connected to the remote destination.
390
 *      @uaddr: Remote and possibly the local address of the new connection.
391
 *      @addrlen: Size of uaddr structure.
392
 *      @flags: Operational flags specified by the user.
393
 *
394
 *      Connect to a remote llc2 mac + sap. The caller must specify the
395
 *      destination mac and address to connect to. If the user hasn't previously
396
 *      called bind(2) with a smac the address of the first interface of the
397
 *      specified arp type will be used.
398
 *      This function will autobind if user did not previously call bind.
399
 *      Returns: 0 upon success, negative otherwise.
400
 */
401
static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
402
                          int addrlen, int flags)
403
{
404
        struct sock *sk = sock->sk;
405
        struct llc_sock *llc = llc_sk(sk);
406
        struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
407
        int rc = -EINVAL;
408
 
409
        lock_sock(sk);
410
        if (unlikely(addrlen != sizeof(*addr)))
411
                goto out;
412
        rc = -EAFNOSUPPORT;
413
        if (unlikely(addr->sllc_family != AF_LLC))
414
                goto out;
415
        if (unlikely(sk->sk_type != SOCK_STREAM))
416
                goto out;
417
        rc = -EALREADY;
418
        if (unlikely(sock->state == SS_CONNECTING))
419
                goto out;
420
        /* bind connection to sap if user hasn't done it. */
421
        if (sock_flag(sk, SOCK_ZAPPED)) {
422
                /* bind to sap with null dev, exclusive */
423
                rc = llc_ui_autobind(sock, addr);
424
                if (rc)
425
                        goto out;
426
        }
427
        llc->daddr.lsap = addr->sllc_sap;
428
        memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
429
        sock->state = SS_CONNECTING;
430
        sk->sk_state   = TCP_SYN_SENT;
431
        llc->link   = llc_ui_next_link_no(llc->sap->laddr.lsap);
432
        rc = llc_establish_connection(sk, llc->dev->dev_addr,
433
                                      addr->sllc_mac, addr->sllc_sap);
434
        if (rc) {
435
                dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
436
                sock->state  = SS_UNCONNECTED;
437
                sk->sk_state = TCP_CLOSE;
438
                goto out;
439
        }
440
 
441
        if (sk->sk_state == TCP_SYN_SENT) {
442
                const long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
443
 
444
                if (!timeo || !llc_ui_wait_for_conn(sk, timeo))
445
                        goto out;
446
 
447
                rc = sock_intr_errno(timeo);
448
                if (signal_pending(current))
449
                        goto out;
450
        }
451
 
452
        if (sk->sk_state == TCP_CLOSE)
453
                goto sock_error;
454
 
455
        sock->state = SS_CONNECTED;
456
        rc = 0;
457
out:
458
        release_sock(sk);
459
        return rc;
460
sock_error:
461
        rc = sock_error(sk) ? : -ECONNABORTED;
462
        sock->state = SS_UNCONNECTED;
463
        goto out;
464
}
465
 
466
/**
467
 *      llc_ui_listen - allow a normal socket to accept incoming connections
468
 *      @sock: Socket to allow incoming connections on.
469
 *      @backlog: Number of connections to queue.
470
 *
471
 *      Allow a normal socket to accept incoming connections.
472
 *      Returns 0 upon success, negative otherwise.
473
 */
474
static int llc_ui_listen(struct socket *sock, int backlog)
475
{
476
        struct sock *sk = sock->sk;
477
        int rc = -EINVAL;
478
 
479
        lock_sock(sk);
480
        if (unlikely(sock->state != SS_UNCONNECTED))
481
                goto out;
482
        rc = -EOPNOTSUPP;
483
        if (unlikely(sk->sk_type != SOCK_STREAM))
484
                goto out;
485
        rc = -EAGAIN;
486
        if (sock_flag(sk, SOCK_ZAPPED))
487
                goto out;
488
        rc = 0;
489
        if (!(unsigned)backlog) /* BSDism */
490
                backlog = 1;
491
        sk->sk_max_ack_backlog = backlog;
492
        if (sk->sk_state != TCP_LISTEN) {
493
                sk->sk_ack_backlog = 0;
494
                sk->sk_state       = TCP_LISTEN;
495
        }
496
        sk->sk_socket->flags |= __SO_ACCEPTCON;
497
out:
498
        release_sock(sk);
499
        return rc;
500
}
501
 
502
static int llc_ui_wait_for_disc(struct sock *sk, long timeout)
503
{
504
        DEFINE_WAIT(wait);
505
        int rc = 0;
506
 
507
        while (1) {
508
                prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
509
                if (sk_wait_event(sk, &timeout, sk->sk_state == TCP_CLOSE))
510
                        break;
511
                rc = -ERESTARTSYS;
512
                if (signal_pending(current))
513
                        break;
514
                rc = -EAGAIN;
515
                if (!timeout)
516
                        break;
517
                rc = 0;
518
        }
519
        finish_wait(sk->sk_sleep, &wait);
520
        return rc;
521
}
522
 
523
static int llc_ui_wait_for_conn(struct sock *sk, long timeout)
524
{
525
        DEFINE_WAIT(wait);
526
 
527
        while (1) {
528
                prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
529
                if (sk_wait_event(sk, &timeout, sk->sk_state != TCP_SYN_SENT))
530
                        break;
531
                if (signal_pending(current) || !timeout)
532
                        break;
533
        }
534
        finish_wait(sk->sk_sleep, &wait);
535
        return timeout;
536
}
537
 
538
static int llc_ui_wait_for_busy_core(struct sock *sk, long timeout)
539
{
540
        DEFINE_WAIT(wait);
541
        struct llc_sock *llc = llc_sk(sk);
542
        int rc;
543
 
544
        while (1) {
545
                prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
546
                rc = 0;
547
                if (sk_wait_event(sk, &timeout,
548
                                  (sk->sk_shutdown & RCV_SHUTDOWN) ||
549
                                  (!llc_data_accept_state(llc->state) &&
550
                                   !llc->remote_busy_flag &&
551
                                   !llc->p_flag)))
552
                        break;
553
                rc = -ERESTARTSYS;
554
                if (signal_pending(current))
555
                        break;
556
                rc = -EAGAIN;
557
                if (!timeout)
558
                        break;
559
        }
560
        finish_wait(sk->sk_sleep, &wait);
561
        return rc;
562
}
563
 
564
static int llc_wait_data(struct sock *sk, long timeo)
565
{
566
        int rc;
567
 
568
        while (1) {
569
                /*
570
                 * POSIX 1003.1g mandates this order.
571
                 */
572
                rc = sock_error(sk);
573
                if (rc)
574
                        break;
575
                rc = 0;
576
                if (sk->sk_shutdown & RCV_SHUTDOWN)
577
                        break;
578
                rc = -EAGAIN;
579
                if (!timeo)
580
                        break;
581
                rc = sock_intr_errno(timeo);
582
                if (signal_pending(current))
583
                        break;
584
                rc = 0;
585
                if (sk_wait_data(sk, &timeo))
586
                        break;
587
        }
588
        return rc;
589
}
590
 
591
/**
592
 *      llc_ui_accept - accept a new incoming connection.
593
 *      @sock: Socket which connections arrive on.
594
 *      @newsock: Socket to move incoming connection to.
595
 *      @flags: User specified operational flags.
596
 *
597
 *      Accept a new incoming connection.
598
 *      Returns 0 upon success, negative otherwise.
599
 */
600
static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
601
{
602
        struct sock *sk = sock->sk, *newsk;
603
        struct llc_sock *llc, *newllc;
604
        struct sk_buff *skb;
605
        int rc = -EOPNOTSUPP;
606
 
607
        dprintk("%s: accepting on %02X\n", __FUNCTION__,
608
                llc_sk(sk)->laddr.lsap);
609
        lock_sock(sk);
610
        if (unlikely(sk->sk_type != SOCK_STREAM))
611
                goto out;
612
        rc = -EINVAL;
613
        if (unlikely(sock->state != SS_UNCONNECTED ||
614
                     sk->sk_state != TCP_LISTEN))
615
                goto out;
616
        /* wait for a connection to arrive. */
617
        if (skb_queue_empty(&sk->sk_receive_queue)) {
618
                rc = llc_wait_data(sk, sk->sk_rcvtimeo);
619
                if (rc)
620
                        goto out;
621
        }
622
        dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
623
                llc_sk(sk)->laddr.lsap);
624
        skb = skb_dequeue(&sk->sk_receive_queue);
625
        rc = -EINVAL;
626
        if (!skb->sk)
627
                goto frees;
628
        rc = 0;
629
        newsk = skb->sk;
630
        /* attach connection to a new socket. */
631
        llc_ui_sk_init(newsock, newsk);
632
        sock_reset_flag(newsk, SOCK_ZAPPED);
633
        newsk->sk_state         = TCP_ESTABLISHED;
634
        newsock->state          = SS_CONNECTED;
635
        llc                     = llc_sk(sk);
636
        newllc                  = llc_sk(newsk);
637
        memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr));
638
        newllc->link = llc_ui_next_link_no(newllc->laddr.lsap);
639
 
640
        /* put original socket back into a clean listen state. */
641
        sk->sk_state = TCP_LISTEN;
642
        sk->sk_ack_backlog--;
643
        dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
644
                llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
645
frees:
646
        kfree_skb(skb);
647
out:
648
        release_sock(sk);
649
        return rc;
650
}
651
 
652
/**
653
 *      llc_ui_recvmsg - copy received data to the socket user.
654
 *      @sock: Socket to copy data from.
655
 *      @msg: Various user space related information.
656
 *      @len: Size of user buffer.
657
 *      @flags: User specified flags.
658
 *
659
 *      Copy received data to the socket user.
660
 *      Returns non-negative upon success, negative otherwise.
661
 */
662
static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
663
                          struct msghdr *msg, size_t len, int flags)
664
{
665
        struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
666
        const int nonblock = flags & MSG_DONTWAIT;
667
        struct sk_buff *skb = NULL;
668
        struct sock *sk = sock->sk;
669
        struct llc_sock *llc = llc_sk(sk);
670
        size_t copied = 0;
671
        u32 peek_seq = 0;
672
        u32 *seq;
673
        unsigned long used;
674
        int target;     /* Read at least this many bytes */
675
        long timeo;
676
 
677
        lock_sock(sk);
678
        copied = -ENOTCONN;
679
        if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN))
680
                goto out;
681
 
682
        timeo = sock_rcvtimeo(sk, nonblock);
683
 
684
        seq = &llc->copied_seq;
685
        if (flags & MSG_PEEK) {
686
                peek_seq = llc->copied_seq;
687
                seq = &peek_seq;
688
        }
689
 
690
        target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
691
        copied = 0;
692
 
693
        do {
694
                u32 offset;
695
 
696
                /*
697
                 * We need to check signals first, to get correct SIGURG
698
                 * handling. FIXME: Need to check this doesn't impact 1003.1g
699
                 * and move it down to the bottom of the loop
700
                 */
701
                if (signal_pending(current)) {
702
                        if (copied)
703
                                break;
704
                        copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
705
                        break;
706
                }
707
 
708
                /* Next get a buffer. */
709
 
710
                skb = skb_peek(&sk->sk_receive_queue);
711
                if (skb) {
712
                        offset = *seq;
713
                        goto found_ok_skb;
714
                }
715
                /* Well, if we have backlog, try to process it now yet. */
716
 
717
                if (copied >= target && !sk->sk_backlog.tail)
718
                        break;
719
 
720
                if (copied) {
721
                        if (sk->sk_err ||
722
                            sk->sk_state == TCP_CLOSE ||
723
                            (sk->sk_shutdown & RCV_SHUTDOWN) ||
724
                            !timeo ||
725
                            (flags & MSG_PEEK))
726
                                break;
727
                } else {
728
                        if (sock_flag(sk, SOCK_DONE))
729
                                break;
730
 
731
                        if (sk->sk_err) {
732
                                copied = sock_error(sk);
733
                                break;
734
                        }
735
                        if (sk->sk_shutdown & RCV_SHUTDOWN)
736
                                break;
737
 
738
                        if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSE) {
739
                                if (!sock_flag(sk, SOCK_DONE)) {
740
                                        /*
741
                                         * This occurs when user tries to read
742
                                         * from never connected socket.
743
                                         */
744
                                        copied = -ENOTCONN;
745
                                        break;
746
                                }
747
                                break;
748
                        }
749
                        if (!timeo) {
750
                                copied = -EAGAIN;
751
                                break;
752
                        }
753
                }
754
 
755
                if (copied >= target) { /* Do not sleep, just process backlog. */
756
                        release_sock(sk);
757
                        lock_sock(sk);
758
                } else
759
                        sk_wait_data(sk, &timeo);
760
 
761
                if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
762
                        if (net_ratelimit())
763
                                printk(KERN_DEBUG "LLC(%s:%d): Application "
764
                                                  "bug, race in MSG_PEEK.\n",
765
                                       current->comm, task_pid_nr(current));
766
                        peek_seq = llc->copied_seq;
767
                }
768
                continue;
769
        found_ok_skb:
770
                /* Ok so how much can we use? */
771
                used = skb->len - offset;
772
                if (len < used)
773
                        used = len;
774
 
775
                if (!(flags & MSG_TRUNC)) {
776
                        int rc = skb_copy_datagram_iovec(skb, offset,
777
                                                         msg->msg_iov, used);
778
                        if (rc) {
779
                                /* Exception. Bailout! */
780
                                if (!copied)
781
                                        copied = -EFAULT;
782
                                break;
783
                        }
784
                }
785
 
786
                *seq += used;
787
                copied += used;
788
                len -= used;
789
 
790
                if (!(flags & MSG_PEEK)) {
791
                        sk_eat_skb(sk, skb, 0);
792
                        *seq = 0;
793
                }
794
 
795
                /* For non stream protcols we get one packet per recvmsg call */
796
                if (sk->sk_type != SOCK_STREAM)
797
                        goto copy_uaddr;
798
 
799
                /* Partial read */
800
                if (used + offset < skb->len)
801
                        continue;
802
        } while (len > 0);
803
 
804
out:
805
        release_sock(sk);
806
        return copied;
807
copy_uaddr:
808
        if (uaddr != NULL && skb != NULL) {
809
                memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
810
                msg->msg_namelen = sizeof(*uaddr);
811
        }
812
        goto out;
813
}
814
 
815
/**
816
 *      llc_ui_sendmsg - Transmit data provided by the socket user.
817
 *      @sock: Socket to transmit data from.
818
 *      @msg: Various user related information.
819
 *      @len: Length of data to transmit.
820
 *
821
 *      Transmit data provided by the socket user.
822
 *      Returns non-negative upon success, negative otherwise.
823
 */
824
static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
825
                          struct msghdr *msg, size_t len)
826
{
827
        struct sock *sk = sock->sk;
828
        struct llc_sock *llc = llc_sk(sk);
829
        struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
830
        int flags = msg->msg_flags;
831
        int noblock = flags & MSG_DONTWAIT;
832
        struct sk_buff *skb;
833
        size_t size = 0;
834
        int rc = -EINVAL, copied = 0, hdrlen;
835
 
836
        dprintk("%s: sending from %02X to %02X\n", __FUNCTION__,
837
                llc->laddr.lsap, llc->daddr.lsap);
838
        lock_sock(sk);
839
        if (addr) {
840
                if (msg->msg_namelen < sizeof(*addr))
841
                        goto release;
842
        } else {
843
                if (llc_ui_addr_null(&llc->addr))
844
                        goto release;
845
                addr = &llc->addr;
846
        }
847
        /* must bind connection to sap if user hasn't done it. */
848
        if (sock_flag(sk, SOCK_ZAPPED)) {
849
                /* bind to sap with null dev, exclusive. */
850
                rc = llc_ui_autobind(sock, addr);
851
                if (rc)
852
                        goto release;
853
        }
854
        hdrlen = llc->dev->hard_header_len + llc_ui_header_len(sk, addr);
855
        size = hdrlen + len;
856
        if (size > llc->dev->mtu)
857
                size = llc->dev->mtu;
858
        copied = size - hdrlen;
859
        release_sock(sk);
860
        skb = sock_alloc_send_skb(sk, size, noblock, &rc);
861
        lock_sock(sk);
862
        if (!skb)
863
                goto release;
864
        skb->dev      = llc->dev;
865
        skb->protocol = llc_proto_type(addr->sllc_arphrd);
866
        skb_reserve(skb, hdrlen);
867
        rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);
868
        if (rc)
869
                goto out;
870
        if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) {
871
                llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac,
872
                                          addr->sllc_sap);
873
                goto out;
874
        }
875
        if (addr->sllc_test) {
876
                llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac,
877
                                            addr->sllc_sap);
878
                goto out;
879
        }
880
        if (addr->sllc_xid) {
881
                llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac,
882
                                           addr->sllc_sap);
883
                goto out;
884
        }
885
        rc = -ENOPROTOOPT;
886
        if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
887
                goto out;
888
        rc = llc_ui_send_data(sk, skb, noblock);
889
out:
890
        if (rc) {
891
                kfree_skb(skb);
892
release:
893
                dprintk("%s: failed sending from %02X to %02X: %d\n",
894
                        __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
895
        }
896
        release_sock(sk);
897
        return rc ? : copied;
898
}
899
 
900
/**
901
 *      llc_ui_getname - return the address info of a socket
902
 *      @sock: Socket to get address of.
903
 *      @uaddr: Address structure to return information.
904
 *      @uaddrlen: Length of address structure.
905
 *      @peer: Does user want local or remote address information.
906
 *
907
 *      Return the address information of a socket.
908
 */
909
static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
910
                          int *uaddrlen, int peer)
911
{
912
        struct sockaddr_llc sllc;
913
        struct sock *sk = sock->sk;
914
        struct llc_sock *llc = llc_sk(sk);
915
        int rc = 0;
916
 
917
        lock_sock(sk);
918
        if (sock_flag(sk, SOCK_ZAPPED))
919
                goto out;
920
        *uaddrlen = sizeof(sllc);
921
        memset(uaddr, 0, *uaddrlen);
922
        if (peer) {
923
                rc = -ENOTCONN;
924
                if (sk->sk_state != TCP_ESTABLISHED)
925
                        goto out;
926
                if(llc->dev)
927
                        sllc.sllc_arphrd = llc->dev->type;
928
                sllc.sllc_sap = llc->daddr.lsap;
929
                memcpy(&sllc.sllc_mac, &llc->daddr.mac, IFHWADDRLEN);
930
        } else {
931
                rc = -EINVAL;
932
                if (!llc->sap)
933
                        goto out;
934
                sllc.sllc_sap = llc->sap->laddr.lsap;
935
 
936
                if (llc->dev) {
937
                        sllc.sllc_arphrd = llc->dev->type;
938
                        memcpy(&sllc.sllc_mac, &llc->dev->dev_addr,
939
                               IFHWADDRLEN);
940
                }
941
        }
942
        rc = 0;
943
        sllc.sllc_family = AF_LLC;
944
        memcpy(uaddr, &sllc, sizeof(sllc));
945
out:
946
        release_sock(sk);
947
        return rc;
948
}
949
 
950
/**
951
 *      llc_ui_ioctl - io controls for PF_LLC
952
 *      @sock: Socket to get/set info
953
 *      @cmd: command
954
 *      @arg: optional argument for cmd
955
 *
956
 *      get/set info on llc sockets
957
 */
958
static int llc_ui_ioctl(struct socket *sock, unsigned int cmd,
959
                        unsigned long arg)
960
{
961
        return -ENOIOCTLCMD;
962
}
963
 
964
/**
965
 *      llc_ui_setsockopt - set various connection specific parameters.
966
 *      @sock: Socket to set options on.
967
 *      @level: Socket level user is requesting operations on.
968
 *      @optname: Operation name.
969
 *      @optval User provided operation data.
970
 *      @optlen: Length of optval.
971
 *
972
 *      Set various connection specific parameters.
973
 */
974
static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
975
                             char __user *optval, int optlen)
976
{
977
        struct sock *sk = sock->sk;
978
        struct llc_sock *llc = llc_sk(sk);
979
        int rc = -EINVAL, opt;
980
 
981
        lock_sock(sk);
982
        if (unlikely(level != SOL_LLC || optlen != sizeof(int)))
983
                goto out;
984
        rc = get_user(opt, (int __user *)optval);
985
        if (rc)
986
                goto out;
987
        rc = -EINVAL;
988
        switch (optname) {
989
        case LLC_OPT_RETRY:
990
                if (opt > LLC_OPT_MAX_RETRY)
991
                        goto out;
992
                llc->n2 = opt;
993
                break;
994
        case LLC_OPT_SIZE:
995
                if (opt > LLC_OPT_MAX_SIZE)
996
                        goto out;
997
                llc->n1 = opt;
998
                break;
999
        case LLC_OPT_ACK_TMR_EXP:
1000
                if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
1001
                        goto out;
1002
                llc->ack_timer.expire = opt * HZ;
1003
                break;
1004
        case LLC_OPT_P_TMR_EXP:
1005
                if (opt > LLC_OPT_MAX_P_TMR_EXP)
1006
                        goto out;
1007
                llc->pf_cycle_timer.expire = opt * HZ;
1008
                break;
1009
        case LLC_OPT_REJ_TMR_EXP:
1010
                if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
1011
                        goto out;
1012
                llc->rej_sent_timer.expire = opt * HZ;
1013
                break;
1014
        case LLC_OPT_BUSY_TMR_EXP:
1015
                if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
1016
                        goto out;
1017
                llc->busy_state_timer.expire = opt * HZ;
1018
                break;
1019
        case LLC_OPT_TX_WIN:
1020
                if (opt > LLC_OPT_MAX_WIN)
1021
                        goto out;
1022
                llc->k = opt;
1023
                break;
1024
        case LLC_OPT_RX_WIN:
1025
                if (opt > LLC_OPT_MAX_WIN)
1026
                        goto out;
1027
                llc->rw = opt;
1028
                break;
1029
        default:
1030
                rc = -ENOPROTOOPT;
1031
                goto out;
1032
        }
1033
        rc = 0;
1034
out:
1035
        release_sock(sk);
1036
        return rc;
1037
}
1038
 
1039
/**
1040
 *      llc_ui_getsockopt - get connection specific socket info
1041
 *      @sock: Socket to get information from.
1042
 *      @level: Socket level user is requesting operations on.
1043
 *      @optname: Operation name.
1044
 *      @optval: Variable to return operation data in.
1045
 *      @optlen: Length of optval.
1046
 *
1047
 *      Get connection specific socket information.
1048
 */
1049
static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
1050
                             char __user *optval, int __user *optlen)
1051
{
1052
        struct sock *sk = sock->sk;
1053
        struct llc_sock *llc = llc_sk(sk);
1054
        int val = 0, len = 0, rc = -EINVAL;
1055
 
1056
        lock_sock(sk);
1057
        if (unlikely(level != SOL_LLC))
1058
                goto out;
1059
        rc = get_user(len, optlen);
1060
        if (rc)
1061
                goto out;
1062
        rc = -EINVAL;
1063
        if (len != sizeof(int))
1064
                goto out;
1065
        switch (optname) {
1066
        case LLC_OPT_RETRY:
1067
                val = llc->n2;                                  break;
1068
        case LLC_OPT_SIZE:
1069
                val = llc->n1;                                  break;
1070
        case LLC_OPT_ACK_TMR_EXP:
1071
                val = llc->ack_timer.expire / HZ;               break;
1072
        case LLC_OPT_P_TMR_EXP:
1073
                val = llc->pf_cycle_timer.expire / HZ;          break;
1074
        case LLC_OPT_REJ_TMR_EXP:
1075
                val = llc->rej_sent_timer.expire / HZ;          break;
1076
        case LLC_OPT_BUSY_TMR_EXP:
1077
                val = llc->busy_state_timer.expire / HZ;        break;
1078
        case LLC_OPT_TX_WIN:
1079
                val = llc->k;                           break;
1080
        case LLC_OPT_RX_WIN:
1081
                val = llc->rw;                          break;
1082
        default:
1083
                rc = -ENOPROTOOPT;
1084
                goto out;
1085
        }
1086
        rc = 0;
1087
        if (put_user(len, optlen) || copy_to_user(optval, &val, len))
1088
                rc = -EFAULT;
1089
out:
1090
        release_sock(sk);
1091
        return rc;
1092
}
1093
 
1094
static struct net_proto_family llc_ui_family_ops = {
1095
        .family = PF_LLC,
1096
        .create = llc_ui_create,
1097
        .owner  = THIS_MODULE,
1098
};
1099
 
1100
static const struct proto_ops llc_ui_ops = {
1101
        .family      = PF_LLC,
1102
        .owner       = THIS_MODULE,
1103
        .release     = llc_ui_release,
1104
        .bind        = llc_ui_bind,
1105
        .connect     = llc_ui_connect,
1106
        .socketpair  = sock_no_socketpair,
1107
        .accept      = llc_ui_accept,
1108
        .getname     = llc_ui_getname,
1109
        .poll        = datagram_poll,
1110
        .ioctl       = llc_ui_ioctl,
1111
        .listen      = llc_ui_listen,
1112
        .shutdown    = llc_ui_shutdown,
1113
        .setsockopt  = llc_ui_setsockopt,
1114
        .getsockopt  = llc_ui_getsockopt,
1115
        .sendmsg     = llc_ui_sendmsg,
1116
        .recvmsg     = llc_ui_recvmsg,
1117
        .mmap        = sock_no_mmap,
1118
        .sendpage    = sock_no_sendpage,
1119
};
1120
 
1121
static char llc_proc_err_msg[] __initdata =
1122
        KERN_CRIT "LLC: Unable to register the proc_fs entries\n";
1123
static char llc_sysctl_err_msg[] __initdata =
1124
        KERN_CRIT "LLC: Unable to register the sysctl entries\n";
1125
static char llc_sock_err_msg[] __initdata =
1126
        KERN_CRIT "LLC: Unable to register the network family\n";
1127
 
1128
static int __init llc2_init(void)
1129
{
1130
        int rc = proto_register(&llc_proto, 0);
1131
 
1132
        if (rc != 0)
1133
                goto out;
1134
 
1135
        llc_build_offset_table();
1136
        llc_station_init();
1137
        llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
1138
        rc = llc_proc_init();
1139
        if (rc != 0) {
1140
                printk(llc_proc_err_msg);
1141
                goto out_unregister_llc_proto;
1142
        }
1143
        rc = llc_sysctl_init();
1144
        if (rc) {
1145
                printk(llc_sysctl_err_msg);
1146
                goto out_proc;
1147
        }
1148
        rc = sock_register(&llc_ui_family_ops);
1149
        if (rc) {
1150
                printk(llc_sock_err_msg);
1151
                goto out_sysctl;
1152
        }
1153
        llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
1154
        llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
1155
out:
1156
        return rc;
1157
out_sysctl:
1158
        llc_sysctl_exit();
1159
out_proc:
1160
        llc_proc_exit();
1161
out_unregister_llc_proto:
1162
        proto_unregister(&llc_proto);
1163
        goto out;
1164
}
1165
 
1166
static void __exit llc2_exit(void)
1167
{
1168
        llc_station_exit();
1169
        llc_remove_pack(LLC_DEST_SAP);
1170
        llc_remove_pack(LLC_DEST_CONN);
1171
        sock_unregister(PF_LLC);
1172
        llc_proc_exit();
1173
        llc_sysctl_exit();
1174
        proto_unregister(&llc_proto);
1175
}
1176
 
1177
module_init(llc2_init);
1178
module_exit(llc2_exit);
1179
 
1180
MODULE_LICENSE("GPL");
1181
MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
1182
MODULE_DESCRIPTION("IEEE 802.2 PF_LLC support");
1183
MODULE_ALIAS_NETPROTO(PF_LLC);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.