~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/x25/af_x25.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      X.25 Packet Layer release 002
  3  *
  4  *      This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  5  *      releases, misbehave and/or generally screw up. It might even work. 
  6  *
  7  *      This code REQUIRES 2.1.15 or higher
  8  *
  9  *      This module:
 10  *              This module is free software; you can redistribute it and/or
 11  *              modify it under the terms of the GNU General Public License
 12  *              as published by the Free Software Foundation; either version
 13  *              2 of the License, or (at your option) any later version.
 14  *
 15  *      History
 16  *      X.25 001        Jonathan Naylor Started coding.
 17  *      X.25 002        Jonathan Naylor Centralised disconnect handling.
 18  *                                      New timer architecture.
 19  *      2000-03-11      Henner Eisen    MSG_EOR handling more POSIX compliant.
 20  *      2000-03-22      Daniela Squassoni Allowed disabling/enabling of 
 21  *                                        facilities negotiation and increased 
 22  *                                        the throughput upper limit.
 23  *      2000-08-27      Arnaldo C. Melo s/suser/capable/ + micro cleanups
 24  *      2000-09-04      Henner Eisen    Set sock->state in x25_accept(). 
 25  *                                      Fixed x25_output() related skb leakage.
 26  *      2000-10-02      Henner Eisen    Made x25_kick() single threaded per socket.
 27  *      2000-10-27      Henner Eisen    MSG_DONTWAIT for fragment allocation.
 28  *      2000-11-14      Henner Eisen    Closing datalink from NETDEV_GOING_DOWN
 29  */
 30 
 31 #include <linux/config.h>
 32 #include <linux/module.h>
 33 #include <linux/errno.h>
 34 #include <linux/types.h>
 35 #include <linux/socket.h>
 36 #include <linux/in.h>
 37 #include <linux/kernel.h>
 38 #include <linux/sched.h>
 39 #include <linux/timer.h>
 40 #include <linux/string.h>
 41 #include <linux/sockios.h>
 42 #include <linux/net.h>
 43 #include <linux/stat.h>
 44 #include <linux/inet.h>
 45 #include <linux/netdevice.h>
 46 #include <linux/if_arp.h>
 47 #include <linux/skbuff.h>
 48 #include <net/sock.h>
 49 #include <asm/segment.h>
 50 #include <asm/system.h>
 51 #include <asm/uaccess.h>
 52 #include <linux/fcntl.h>
 53 #include <linux/termios.h>      /* For TIOCINQ/OUTQ */
 54 #include <linux/mm.h>
 55 #include <linux/interrupt.h>
 56 #include <linux/notifier.h>
 57 #include <linux/proc_fs.h>
 58 #include <linux/init.h>
 59 #include <net/x25.h>
 60 
 61 int sysctl_x25_restart_request_timeout = X25_DEFAULT_T20;
 62 int sysctl_x25_call_request_timeout    = X25_DEFAULT_T21;
 63 int sysctl_x25_reset_request_timeout   = X25_DEFAULT_T22;
 64 int sysctl_x25_clear_request_timeout   = X25_DEFAULT_T23;
 65 int sysctl_x25_ack_holdback_timeout    = X25_DEFAULT_T2;
 66 
 67 static struct sock *volatile x25_list /* = NULL initially */;
 68 
 69 static struct proto_ops x25_proto_ops;
 70 
 71 static x25_address null_x25_address = {"               "};
 72 
 73 int x25_addr_ntoa(unsigned char *p, x25_address *called_addr, x25_address *calling_addr)
 74 {
 75         int called_len, calling_len;
 76         char *called, *calling;
 77         int i;
 78 
 79         called_len  = (*p >> 0) & 0x0F;
 80         calling_len = (*p >> 4) & 0x0F;
 81 
 82         called  = called_addr->x25_addr;
 83         calling = calling_addr->x25_addr;
 84         p++;
 85 
 86         for (i = 0; i < (called_len + calling_len); i++) {
 87                 if (i < called_len) {
 88                         if (i % 2 != 0) {
 89                                 *called++ = ((*p >> 0) & 0x0F) + '';
 90                                 p++;
 91                         } else {
 92                                 *called++ = ((*p >> 4) & 0x0F) + '';
 93                         }
 94                 } else {
 95                         if (i % 2 != 0) {
 96                                 *calling++ = ((*p >> 0) & 0x0F) + '';
 97                                 p++;
 98                         } else {
 99                                 *calling++ = ((*p >> 4) & 0x0F) + '';
100                         }
101                 }
102         }
103 
104         *called  = '\0';
105         *calling = '\0';
106 
107         return 1 + (called_len + calling_len + 1) / 2;
108 }
109 
110 int x25_addr_aton(unsigned char *p, x25_address *called_addr, x25_address *calling_addr)
111 {
112         unsigned int called_len, calling_len;
113         char *called, *calling;
114         int i;
115 
116         called  = called_addr->x25_addr;
117         calling = calling_addr->x25_addr;
118 
119         called_len  = strlen(called);
120         calling_len = strlen(calling);
121 
122         *p++ = (calling_len << 4) | (called_len << 0);
123 
124         for (i = 0; i < (called_len + calling_len); i++) {
125                 if (i < called_len) {
126                         if (i % 2 != 0) {
127                                 *p |= (*called++ - '') << 0;
128                                 p++;
129                         } else {
130                                 *p = 0x00;
131                                 *p |= (*called++ - '') << 4;
132                         }
133                 } else {
134                         if (i % 2 != 0) {
135                                 *p |= (*calling++ - '') << 0;
136                                 p++;
137                         } else {
138                                 *p = 0x00;
139                                 *p |= (*calling++ - '') << 4;
140                         }
141                 }
142         }
143 
144         return 1 + (called_len + calling_len + 1) / 2;
145 }
146 
147 /*
148  *      Socket removal during an interrupt is now safe.
149  */
150 static void x25_remove_socket(struct sock *sk)
151 {
152         struct sock *s;
153         unsigned long flags;
154 
155         save_flags(flags);
156         cli();
157 
158         if ((s = x25_list) == sk) {
159                 x25_list = s->next;
160                 restore_flags(flags);
161                 return;
162         }
163 
164         while (s != NULL && s->next != NULL) {
165                 if (s->next == sk) {
166                         s->next = sk->next;
167                         restore_flags(flags);
168                         return;
169                 }
170 
171                 s = s->next;
172         }
173 
174         restore_flags(flags);
175 }
176 
177 /*
178  *      Kill all bound sockets on a dropped device.
179  */
180 static void x25_kill_by_device(struct net_device *dev)
181 {
182         struct sock *s;
183 
184         for (s = x25_list; s != NULL; s = s->next)
185                 if (s->protinfo.x25->neighbour &&
186                     s->protinfo.x25->neighbour->dev == dev)
187                         x25_disconnect(s, ENETUNREACH, 0, 0);
188 }
189 
190 /*
191  *      Handle device status changes.
192  */
193 static int x25_device_event(struct notifier_block *this, unsigned long event, void *ptr)
194 {
195         struct net_device *dev = (struct net_device *)ptr;
196         struct x25_neigh *neigh;
197 
198         if (dev->type == ARPHRD_X25
199 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
200          || dev->type == ARPHRD_ETHER
201 #endif
202          ) {
203                 switch (event) {
204                         case NETDEV_UP:
205                                 x25_link_device_up(dev);
206                                 break;
207                         case NETDEV_GOING_DOWN:
208                                 if ((neigh = x25_get_neigh(dev)))
209                                         x25_terminate_link(neigh);
210                                 break;
211                         case NETDEV_DOWN:
212                                 x25_kill_by_device(dev);
213                                 x25_route_device_down(dev);
214                                 x25_link_device_down(dev);
215                                 break;
216                 }
217         }
218 
219         return NOTIFY_DONE;
220 }
221 
222 /*
223  *      Add a socket to the bound sockets list.
224  */
225 static void x25_insert_socket(struct sock *sk)
226 {
227         unsigned long flags;
228 
229         save_flags(flags);
230         cli();
231 
232         sk->next = x25_list;
233         x25_list = sk;
234 
235         restore_flags(flags);
236 }
237 
238 /*
239  *      Find a socket that wants to accept the Call Request we just
240  *      received.
241  */
242 static struct sock *x25_find_listener(x25_address *addr)
243 {
244         unsigned long flags;
245         struct sock *s;
246 
247         save_flags(flags);
248         cli();
249 
250         for (s = x25_list; s != NULL; s = s->next) {
251                 if ((strcmp(addr->x25_addr, s->protinfo.x25->source_addr.x25_addr) == 0 ||
252                      strcmp(addr->x25_addr, null_x25_address.x25_addr) == 0) &&
253                      s->state == TCP_LISTEN) {
254                         restore_flags(flags);
255                         return s;
256                 }
257         }
258 
259         restore_flags(flags);
260         return NULL;
261 }
262 
263 /*
264  *      Find a connected X.25 socket given my LCI and neighbour.
265  */
266 struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
267 {
268         struct sock *s;
269         unsigned long flags;
270 
271         save_flags(flags);
272         cli();
273 
274         for (s = x25_list; s != NULL; s = s->next) {
275                 if (s->protinfo.x25->lci == lci && s->protinfo.x25->neighbour == neigh) {
276                         restore_flags(flags);
277                         return s;
278                 }
279         }
280 
281         restore_flags(flags);
282         return NULL;
283 }
284 
285 /*
286  *      Find a unique LCI for a given device.
287  */
288 unsigned int x25_new_lci(struct x25_neigh *neigh)
289 {
290         unsigned int lci = 1;
291 
292         while (x25_find_socket(lci, neigh) != NULL) {
293                 lci++;
294                 if (lci == 4096) return 0;
295         }
296 
297         return lci;
298 }
299 
300 /*
301  *      Deferred destroy.
302  */
303 void x25_destroy_socket(struct sock *);
304 
305 /*
306  *      handler for deferred kills.
307  */
308 static void x25_destroy_timer(unsigned long data)
309 {
310         x25_destroy_socket((struct sock *)data);
311 }
312 
313 /*
314  *      This is called from user mode and the timers. Thus it protects itself against
315  *      interrupt users but doesn't worry about being called during work.
316  *      Once it is removed from the queue no interrupt or bottom half will
317  *      touch it and we are (fairly 8-) ) safe.
318  */
319 void x25_destroy_socket(struct sock *sk)        /* Not static as it's used by the timer */
320 {
321         struct sk_buff *skb;
322         unsigned long flags;
323 
324         save_flags(flags);
325         cli();
326 
327         x25_stop_heartbeat(sk);
328         x25_stop_timer(sk);
329 
330         x25_remove_socket(sk);
331         x25_clear_queues(sk);           /* Flush the queues */
332 
333         while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
334                 if (skb->sk != sk) {            /* A pending connection */
335                         skb->sk->dead = 1;      /* Queue the unaccepted socket for death */
336                         x25_start_heartbeat(skb->sk);
337                         skb->sk->protinfo.x25->state = X25_STATE_0;
338                 }
339 
340                 kfree_skb(skb);
341         }
342 
343         if (atomic_read(&sk->wmem_alloc) != 0 || atomic_read(&sk->rmem_alloc) != 0) {
344                 /* Defer: outstanding buffers */
345                 init_timer(&sk->timer);
346                 sk->timer.expires  = jiffies + 10 * HZ;
347                 sk->timer.function = x25_destroy_timer;
348                 sk->timer.data     = (unsigned long)sk;
349                 add_timer(&sk->timer);
350         } else {
351                 sk_free(sk);
352                 MOD_DEC_USE_COUNT;
353         }
354 
355         restore_flags(flags);
356 }
357 
358 /*
359  *      Handling for system calls applied via the various interfaces to a
360  *      X.25 socket object.
361  */
362 
363 static int x25_setsockopt(struct socket *sock, int level, int optname,
364         char *optval, int optlen)
365 {
366         struct sock *sk = sock->sk;
367         int opt;
368 
369         if (level != SOL_X25)
370                 return -ENOPROTOOPT;
371 
372         if (optlen < sizeof(int))
373                 return-EINVAL;
374 
375         if (get_user(opt, (int *)optval))
376                 return -EFAULT;
377 
378         switch (optname) {
379                 case X25_QBITINCL:
380                         sk->protinfo.x25->qbitincl = opt ? 1 : 0;
381                         return 0;
382 
383                 default:
384                         return -ENOPROTOOPT;
385         }
386 }
387 
388 static int x25_getsockopt(struct socket *sock, int level, int optname,
389         char *optval, int *optlen)
390 {
391         struct sock *sk = sock->sk;
392         int val = 0;
393         int len; 
394         
395         if (level != SOL_X25)
396                 return -ENOPROTOOPT;
397 
398         if (get_user(len, optlen))
399                 return -EFAULT;
400 
401         switch (optname) {
402                 case X25_QBITINCL:
403                         val = sk->protinfo.x25->qbitincl;
404                         break;
405 
406                 default:
407                         return -ENOPROTOOPT;
408         }
409 
410         len = min(len, sizeof(int));
411 
412         if (put_user(len, optlen))
413                 return -EFAULT;
414 
415         return copy_to_user(optval, &val, len) ? -EFAULT : 0;
416 }
417 
418 static int x25_listen(struct socket *sock, int backlog)
419 {
420         struct sock *sk = sock->sk;
421 
422         if (sk->state != TCP_LISTEN) {
423                 memset(&sk->protinfo.x25->dest_addr, '\0', X25_ADDR_LEN);
424                 sk->max_ack_backlog = backlog;
425                 sk->state           = TCP_LISTEN;
426                 return 0;
427         }
428 
429         return -EOPNOTSUPP;
430 }
431 
432 static struct sock *x25_alloc_socket(void)
433 {
434         struct sock *sk;
435         x25_cb *x25;
436 
437         if ((sk = sk_alloc(AF_X25, GFP_ATOMIC, 1)) == NULL)
438                 return NULL;
439 
440         if ((x25 = kmalloc(sizeof(*x25), GFP_ATOMIC)) == NULL) {
441                 sk_free(sk);
442                 return NULL;
443         }
444 
445         memset(x25, 0x00, sizeof(*x25));
446 
447         x25->sk          = sk;
448         sk->protinfo.x25 = x25;
449 
450         MOD_INC_USE_COUNT;
451 
452         sock_init_data(NULL, sk);
453 
454         skb_queue_head_init(&x25->ack_queue);
455         skb_queue_head_init(&x25->fragment_queue);
456         skb_queue_head_init(&x25->interrupt_in_queue);
457         skb_queue_head_init(&x25->interrupt_out_queue);
458 
459         return sk;
460 }
461 
462 static int x25_create(struct socket *sock, int protocol)
463 {
464         struct sock *sk;
465         x25_cb *x25;
466 
467         if (sock->type != SOCK_SEQPACKET || protocol != 0)
468                 return -ESOCKTNOSUPPORT;
469 
470         if ((sk = x25_alloc_socket()) == NULL)
471                 return -ENOMEM;
472 
473         x25 = sk->protinfo.x25;
474 
475         sock_init_data(sock, sk);
476 
477         init_timer(&x25->timer);
478 
479         sock->ops    = &x25_proto_ops;
480         sk->protocol = protocol;
481         sk->backlog_rcv = x25_backlog_rcv;
482 
483         x25->t21   = sysctl_x25_call_request_timeout;
484         x25->t22   = sysctl_x25_reset_request_timeout;
485         x25->t23   = sysctl_x25_clear_request_timeout;
486         x25->t2    = sysctl_x25_ack_holdback_timeout;
487         x25->state = X25_STATE_0;
488 
489         x25->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
490         x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
491         x25->facilities.pacsize_in  = X25_DEFAULT_PACKET_SIZE;
492         x25->facilities.pacsize_out = X25_DEFAULT_PACKET_SIZE;
493         x25->facilities.throughput  = X25_DEFAULT_THROUGHPUT;
494         x25->facilities.reverse     = X25_DEFAULT_REVERSE;
495 
496         return 0;
497 }
498 
499 static struct sock *x25_make_new(struct sock *osk)
500 {
501         struct sock *sk;
502         x25_cb *x25;
503 
504         if (osk->type != SOCK_SEQPACKET)
505                 return NULL;
506 
507         if ((sk = x25_alloc_socket()) == NULL)
508                 return NULL;
509 
510         x25 = sk->protinfo.x25;
511 
512         sk->type        = osk->type;
513         sk->socket      = osk->socket;
514         sk->priority    = osk->priority;
515         sk->protocol    = osk->protocol;
516         sk->rcvbuf      = osk->rcvbuf;
517         sk->sndbuf      = osk->sndbuf;
518         sk->debug       = osk->debug;
519         sk->state       = TCP_ESTABLISHED;
520         sk->sleep       = osk->sleep;
521         sk->zapped      = osk->zapped;
522         sk->backlog_rcv = osk->backlog_rcv;
523 
524         x25->t21        = osk->protinfo.x25->t21;
525         x25->t22        = osk->protinfo.x25->t22;
526         x25->t23        = osk->protinfo.x25->t23;
527         x25->t2         = osk->protinfo.x25->t2;
528 
529         x25->facilities = osk->protinfo.x25->facilities;
530 
531         x25->qbitincl   = osk->protinfo.x25->qbitincl;
532 
533         init_timer(&x25->timer);
534 
535         return sk;
536 }
537 
538 static int x25_release(struct socket *sock)
539 {
540         struct sock *sk = sock->sk;
541 
542         if (sk == NULL) return 0;
543 
544         switch (sk->protinfo.x25->state) {
545 
546                 case X25_STATE_0:
547                 case X25_STATE_2:
548                         x25_disconnect(sk, 0, 0, 0);
549                         x25_destroy_socket(sk);
550                         break;
551 
552                 case X25_STATE_1:
553                 case X25_STATE_3:
554                 case X25_STATE_4:
555                         x25_clear_queues(sk);
556                         x25_write_internal(sk, X25_CLEAR_REQUEST);
557                         x25_start_t23timer(sk);
558                         sk->protinfo.x25->state = X25_STATE_2;
559                         sk->state               = TCP_CLOSE;
560                         sk->shutdown           |= SEND_SHUTDOWN;
561                         sk->state_change(sk);
562                         sk->dead                = 1;
563                         sk->destroy             = 1;
564                         break;
565 
566                 default:
567                         break;
568         }
569 
570         sock->sk   = NULL;      
571         sk->socket = NULL;      /* Not used, but we should do this */
572 
573         return 0;
574 }
575 
576 static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
577 {
578         struct sock *sk = sock->sk;
579         struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
580 
581         if (sk->zapped == 0)
582                 return -EINVAL;
583 
584         if (addr_len != sizeof(struct sockaddr_x25))
585                 return -EINVAL;
586 
587         if (addr->sx25_family != AF_X25)
588                 return -EINVAL;
589 
590         sk->protinfo.x25->source_addr = addr->sx25_addr;
591 
592         x25_insert_socket(sk);
593 
594         sk->zapped = 0;
595 
596         SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
597 
598         return 0;
599 }
600 
601 static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
602 {
603         struct sock *sk = sock->sk;
604         struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
605         struct net_device *dev;
606 
607         if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
608                 sock->state = SS_CONNECTED;
609                 return 0;       /* Connect completed during a ERESTARTSYS event */
610         }
611 
612         if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) {
613                 sock->state = SS_UNCONNECTED;
614                 return -ECONNREFUSED;
615         }
616 
617         if (sk->state == TCP_ESTABLISHED)
618                 return -EISCONN;        /* No reconnect on a seqpacket socket */
619 
620         sk->state   = TCP_CLOSE;        
621         sock->state = SS_UNCONNECTED;
622 
623         if (addr_len != sizeof(struct sockaddr_x25))
624                 return -EINVAL;
625 
626         if (addr->sx25_family != AF_X25)
627                 return -EINVAL;
628 
629         if ((dev = x25_get_route(&addr->sx25_addr)) == NULL)
630                 return -ENETUNREACH;
631 
632         if ((sk->protinfo.x25->neighbour = x25_get_neigh(dev)) == NULL)
633                 return -ENETUNREACH;
634 
635         x25_limit_facilities(&sk->protinfo.x25->facilities,
636                              sk->protinfo.x25->neighbour);
637 
638         if ((sk->protinfo.x25->lci = x25_new_lci(sk->protinfo.x25->neighbour)) == 0)
639                 return -ENETUNREACH;
640 
641         if (sk->zapped)         /* Must bind first - autobinding does not work */
642                 return -EINVAL;
643 
644         if (strcmp(sk->protinfo.x25->source_addr.x25_addr, null_x25_address.x25_addr) == 0)
645                 memset(&sk->protinfo.x25->source_addr, '\0', X25_ADDR_LEN);
646 
647         sk->protinfo.x25->dest_addr = addr->sx25_addr;
648 
649         /* Move to connecting socket, start sending Connect Requests */
650         sock->state   = SS_CONNECTING;
651         sk->state     = TCP_SYN_SENT;
652 
653         sk->protinfo.x25->state = X25_STATE_1;
654 
655         x25_write_internal(sk, X25_CALL_REQUEST);
656 
657         x25_start_heartbeat(sk);
658         x25_start_t21timer(sk);
659 
660         /* Now the loop */
661         if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
662                 return -EINPROGRESS;
663 
664         cli();  /* To avoid races on the sleep */
665 
666         /*
667          * A Clear Request or timeout or failed routing will go to closed.
668          */
669         while (sk->state == TCP_SYN_SENT) {
670                 interruptible_sleep_on(sk->sleep);
671                 if (signal_pending(current)) {
672                         sti();
673                         return -ERESTARTSYS;
674                 }
675         }
676 
677         if (sk->state != TCP_ESTABLISHED) {
678                 sti();
679                 sock->state = SS_UNCONNECTED;
680                 return sock_error(sk);  /* Always set at this point */
681         }
682 
683         sock->state = SS_CONNECTED;
684 
685         sti();
686 
687         return 0;
688 }
689         
690 static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
691 {
692         struct sock *sk;
693         struct sock *newsk;
694         struct sk_buff *skb;
695 
696         if ((sk = sock->sk) == NULL)
697                 return -EINVAL;
698 
699         if (sk->type != SOCK_SEQPACKET)
700                 return -EOPNOTSUPP;
701 
702         if (sk->state != TCP_LISTEN)
703                 return -EINVAL;
704 
705         /*
706          *      The write queue this time is holding sockets ready to use
707          *      hooked into the CALL INDICATION we saved
708          */
709         do {
710                 cli();
711                 if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
712                         if (flags & O_NONBLOCK) {
713                                 sti();
714                                 return -EWOULDBLOCK;
715                         }
716                         interruptible_sleep_on(sk->sleep);
717                         if (signal_pending(current)) {
718                                 sti();
719                                 return -ERESTARTSYS;
720                         }
721                 }
722         } while (skb == NULL);
723 
724         newsk = skb->sk;
725         newsk->pair = NULL;
726         newsk->socket = newsock;
727         newsk->sleep = &newsock->wait;
728         sti();
729 
730         /* Now attach up the new socket */
731         skb->sk = NULL;
732         kfree_skb(skb);
733         sk->ack_backlog--;
734         newsock->sk = newsk;
735         newsock->state = SS_CONNECTED;
736 
737         return 0;
738 }
739 
740 static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
741 {
742         struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
743         struct sock *sk = sock->sk;
744 
745         if (peer != 0) {
746                 if (sk->state != TCP_ESTABLISHED)
747                         return -ENOTCONN;
748                 sx25->sx25_addr   = sk->protinfo.x25->dest_addr;
749         } else {
750                 sx25->sx25_addr   = sk->protinfo.x25->source_addr;
751         }
752 
753         sx25->sx25_family = AF_X25;
754         *uaddr_len = sizeof(struct sockaddr_x25);
755 
756         return 0;
757 }
758  
759 int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned int lci)
760 {
761         struct sock *sk;
762         struct sock *make;
763         x25_address source_addr, dest_addr;
764         struct x25_facilities facilities;
765         int len;
766 
767         /*
768          *      Remove the LCI and frame type.
769          */
770         skb_pull(skb, X25_STD_MIN_LEN);
771 
772         /*
773          *      Extract the X.25 addresses and convert them to ASCII strings,
774          *      and remove them.
775          */
776         skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
777 
778         /*
779          *      Find a listener for the particular address.
780          */
781         sk = x25_find_listener(&source_addr);
782 
783         /*
784          *      We can't accept the Call Request.
785          */
786         if (sk == NULL || sk->ack_backlog == sk->max_ack_backlog) {
787                 x25_transmit_clear_request(neigh, lci, 0x01);
788                 return 0;
789         }
790 
791         /*
792          *      Try to reach a compromise on the requested facilities.
793          */
794         if ((len = x25_negotiate_facilities(skb, sk, &facilities)) == -1) {
795                 x25_transmit_clear_request(neigh, lci, 0x01);
796                 return 0;
797         }
798 
799         /*
800          * current neighbour/link might impose additional limits
801          * on certain facilties
802          */
803 
804         x25_limit_facilities(&facilities,neigh);
805 
806         /*
807          *      Try to create a new socket.
808          */
809         if ((make = x25_make_new(sk)) == NULL) {
810                 x25_transmit_clear_request(neigh, lci, 0x01);
811                 return 0;
812         }
813 
814         /*
815          *      Remove the facilities, leaving any Call User Data.
816          */
817         skb_pull(skb, len);
818 
819         skb->sk     = make;
820         make->state = TCP_ESTABLISHED;
821 
822         make->protinfo.x25->lci           = lci;
823         make->protinfo.x25->dest_addr     = dest_addr;
824         make->protinfo.x25->source_addr   = source_addr;
825         make->protinfo.x25->neighbour     = neigh;
826         make->protinfo.x25->facilities    = facilities;
827         make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask;
828 
829         x25_write_internal(make, X25_CALL_ACCEPTED);
830 
831         /*
832          *      Incoming Call User Data.
833          */
834         if (skb->len >= 0) {
835                 memcpy(make->protinfo.x25->calluserdata.cuddata, skb->data, skb->len);
836                 make->protinfo.x25->calluserdata.cudlength = skb->len;
837         }
838 
839         make->protinfo.x25->state = X25_STATE_3;
840 
841         sk->ack_backlog++;
842         make->pair = sk;
843 
844         x25_insert_socket(make);
845 
846         skb_queue_head(&sk->receive_queue, skb);
847 
848         x25_start_heartbeat(make);
849 
850         if (!sk->dead)
851                 sk->data_ready(sk, skb->len);
852 
853         return 1;
854 }
855 
856 static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
857 {
858         struct sock *sk = sock->sk;
859         struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name;
860         int err;
861         struct sockaddr_x25 sx25;
862         struct sk_buff *skb;
863         unsigned char *asmptr;
864         int size, qbit = 0;
865 
866         if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB | MSG_EOR))
867                 return -EINVAL;
868 
869         /* we currently don't support segmented records at the user interface */
870         if (!(msg->msg_flags & (MSG_EOR|MSG_OOB)))
871                 return -EINVAL;
872 
873         if (sk->zapped)
874                 return -EADDRNOTAVAIL;
875 
876         if (sk->shutdown & SEND_SHUTDOWN) {
877                 send_sig(SIGPIPE, current, 0);
878                 return -EPIPE;
879         }
880 
881         if (sk->protinfo.x25->neighbour == NULL)
882                 return -ENETUNREACH;
883 
884         if (usx25 != NULL) {
885                 if (msg->msg_namelen < sizeof(sx25))
886                         return -EINVAL;
887                 sx25 = *usx25;
888                 if (strcmp(sk->protinfo.x25->dest_addr.x25_addr, sx25.sx25_addr.x25_addr) != 0)
889                         return -EISCONN;
890                 if (sx25.sx25_family != AF_X25)
891                         return -EINVAL;
892         } else {
893                 /*
894                  *      FIXME 1003.1g - if the socket is like this because
895                  *      it has become closed (not started closed) we ought
896                  *      to SIGPIPE, EPIPE;
897                  */
898                 if (sk->state != TCP_ESTABLISHED)
899                         return -ENOTCONN;
900 
901                 sx25.sx25_family = AF_X25;
902                 sx25.sx25_addr   = sk->protinfo.x25->dest_addr;
903         }
904 
905         SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
906 
907         /* Build a packet */
908         SOCK_DEBUG(sk, "x25_sendmsg: sendto: building packet.\n");
909 
910         if ((msg->msg_flags & MSG_OOB) && len > 32)
911                 len = 32;
912 
913         size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
914 
915         if ((skb = sock_alloc_send_skb(sk, size, 0, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
916                 return err;
917         X25_SKB_CB(skb)->flags = msg->msg_flags;
918 
919         skb_reserve(skb, X25_MAX_L2_LEN + X25_EXT_MIN_LEN);
920 
921         /*
922          *      Put the data on the end
923          */
924         SOCK_DEBUG(sk, "x25_sendmsg: Copying user data\n");
925 
926         asmptr = skb->h.raw = skb_put(skb, len);
927 
928         memcpy_fromiovec(asmptr, msg->msg_iov, len);
929 
930         /*
931          *      If the Q BIT Include socket option is in force, the first
932          *      byte of the user data is the logical value of the Q Bit.
933          */
934         if (sk->protinfo.x25->qbitincl) {
935                 qbit = skb->data[0];
936                 skb_pull(skb, 1);
937         }
938 
939         /*
940          *      Push down the X.25 header
941          */
942         SOCK_DEBUG(sk, "x25_sendmsg: Building X.25 Header.\n");
943 
944         if (msg->msg_flags & MSG_OOB) {
945                 if (sk->protinfo.x25->neighbour->extended) {
946                         asmptr    = skb_push(skb, X25_STD_MIN_LEN);
947                         *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
948                         *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;
949                         *asmptr++ = X25_INTERRUPT;
950                 } else {
951                         asmptr    = skb_push(skb, X25_STD_MIN_LEN);
952                         *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
953                         *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;
954                         *asmptr++ = X25_INTERRUPT;
955                 }
956         } else {
957                 if (sk->protinfo.x25->neighbour->extended) {
958                         /* Build an Extended X.25 header */
959                         asmptr    = skb_push(skb, X25_EXT_MIN_LEN);
960                         *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_EXTSEQ;
961                         *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;
962                         *asmptr++ = X25_DATA;
963                         *asmptr++ = X25_DATA;
964                 } else {
965                         /* Build an Standard X.25 header */
966                         asmptr    = skb_push(skb, X25_STD_MIN_LEN);
967                         *asmptr++ = ((sk->protinfo.x25->lci >> 8) & 0x0F) | X25_GFI_STDSEQ;
968                         *asmptr++ = (sk->protinfo.x25->lci >> 0) & 0xFF;
969                         *asmptr++ = X25_DATA;
970                 }
971 
972                 if (qbit)
973                         skb->data[0] |= X25_Q_BIT;
974         }
975 
976         SOCK_DEBUG(sk, "x25_sendmsg: Built header.\n");
977         SOCK_DEBUG(sk, "x25_sendmsg: Transmitting buffer\n");
978 
979         if (sk->state != TCP_ESTABLISHED) {
980                 kfree_skb(skb);
981                 return -ENOTCONN;
982         }
983 
984         if (msg->msg_flags & MSG_OOB) {
985                 skb_queue_tail(&sk->protinfo.x25->interrupt_out_queue, skb);
986         } else {
987                 len = x25_output(sk, skb);
988                 if(len<0){
989                         kfree_skb(skb);
990                 } else {
991                         if(sk->protinfo.x25->qbitincl) len++;
992                 }
993         }
994 
995         /*
996          * lock_sock() is currently only used to serialize this x25_kick()
997          * against input-driven x25_kick() calls. It currently only blocks
998          * incoming packets for this socket and does not protect against
999          * any other socket state changes and is not called from anywhere
1000          * else. As x25_kick() cannot block and as long as all socket
1001          * operations are BKL-wrapped, we don't need take to care about
1002          * purging the backlog queue in x25_release().
1003          *
1004          * Using lock_sock() to protect all socket operations entirely
1005          * (and making the whole x25 stack SMP aware) unfortunately would
1006          * require major changes to {send,recv}msg and skb allocation methods.
1007          * -> 2.5 ;)
1008          */
1009         lock_sock(sk);
1010         x25_kick(sk);
1011         release_sock(sk);
1012 
1013         return len;
1014 }
1015 
1016 
1017 static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
1018 {
1019         struct sock *sk = sock->sk;
1020         struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name;
1021         int copied, qbit;
1022         struct sk_buff *skb;
1023         unsigned char *asmptr;
1024         int er;
1025 
1026         /*
1027          * This works for seqpacket too. The receiver has ordered the queue for
1028          * us! We do one quick check first though
1029          */
1030         if (sk->state != TCP_ESTABLISHED)
1031                 return -ENOTCONN;
1032 
1033         if (flags & MSG_OOB) {
1034                 if (sk->urginline || skb_peek(&sk->protinfo.x25->interrupt_in_queue) == NULL)
1035                         return -EINVAL;
1036 
1037                 skb = skb_dequeue(&sk->protinfo.x25->interrupt_in_queue);
1038 
1039                 skb_pull(skb, X25_STD_MIN_LEN);
1040 
1041                 /*
1042                  *      No Q bit information on Interrupt data.
1043                  */
1044                 if (sk->protinfo.x25->qbitincl) {
1045                         asmptr  = skb_push(skb, 1);
1046                         *asmptr = 0x00;
1047                 }
1048 
1049                 msg->msg_flags |= MSG_OOB;
1050         } else {
1051                 /* Now we can treat all alike */
1052                 if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)
1053                         return er;
1054 
1055                 qbit = (skb->data[0] & X25_Q_BIT) == X25_Q_BIT;
1056 
1057                 skb_pull(skb, (sk->protinfo.x25->neighbour->extended) ? X25_EXT_MIN_LEN : X25_STD_MIN_LEN);
1058 
1059                 if (sk->protinfo.x25->qbitincl) {
1060                         asmptr  = skb_push(skb, 1);
1061                         *asmptr = qbit;
1062                 }
1063         }
1064 
1065         skb->h.raw = skb->data;
1066 
1067         copied = skb->len;
1068 
1069         if (copied > size) {
1070                 copied = size;
1071                 msg->msg_flags |= MSG_TRUNC;
1072         }
1073 
1074         /* Currently, each datagram always contains a complete record */ 
1075         msg->msg_flags |= MSG_EOR;
1076 
1077         skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
1078 
1079         if (sx25 != NULL) {
1080                 sx25->sx25_family = AF_X25;
1081                 sx25->sx25_addr   = sk->protinfo.x25->dest_addr;
1082         }
1083 
1084         msg->msg_namelen = sizeof(struct sockaddr_x25);
1085 
1086         skb_free_datagram(sk, skb);
1087 
1088         return copied;
1089 }
1090 
1091 
1092 static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
1093 {
1094         struct sock *sk = sock->sk;
1095 
1096         switch (cmd) {
1097                 case TIOCOUTQ: {
1098                         int amount;
1099                         amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
1100                         if (amount < 0)
1101                                 amount = 0;
1102                         return put_user(amount, (unsigned int *)arg);
1103                 }
1104 
1105                 case TIOCINQ: {
1106                         struct sk_buff *skb;
1107                         int amount = 0;
1108                         /* These two are safe on a single CPU system as only user tasks fiddle here */
1109                         if ((skb = skb_peek(&sk->receive_queue)) != NULL)
1110                                 amount = skb->len;
1111                         return put_user(amount, (unsigned int *)arg);
1112                 }
1113 
1114                 case SIOCGSTAMP:
1115                         if (sk != NULL) {
1116                                 if (sk->stamp.tv_sec == 0)
1117                                         return -ENOENT;
1118                                 return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
1119                         }
1120                         return -EINVAL;
1121 
1122                 case SIOCGIFADDR:
1123                 case SIOCSIFADDR:
1124                 case SIOCGIFDSTADDR:
1125                 case SIOCSIFDSTADDR:
1126                 case SIOCGIFBRDADDR:
1127                 case SIOCSIFBRDADDR:
1128                 case SIOCGIFNETMASK:
1129                 case SIOCSIFNETMASK:
1130                 case SIOCGIFMETRIC:
1131                 case SIOCSIFMETRIC:
1132                         return -EINVAL;
1133 
1134                 case SIOCADDRT:
1135                 case SIOCDELRT:
1136                         if (!capable(CAP_NET_ADMIN)) return -EPERM;
1137                         return x25_route_ioctl(cmd, (void *)arg);
1138 
1139                 case SIOCX25GSUBSCRIP:
1140                         return x25_subscr_ioctl(cmd, (void *)arg);
1141 
1142                 case SIOCX25SSUBSCRIP:
1143                         if (!capable(CAP_NET_ADMIN)) return -EPERM;
1144                         return x25_subscr_ioctl(cmd, (void *)arg);
1145 
1146                 case SIOCX25GFACILITIES: {
1147                         struct x25_facilities facilities;
1148                         facilities = sk->protinfo.x25->facilities;
1149                         return copy_to_user((void *)arg, &facilities, sizeof(facilities)) ? -EFAULT : 0;
1150                 }
1151 
1152                 case SIOCX25SFACILITIES: {
1153                         struct x25_facilities facilities;
1154                         if (copy_from_user(&facilities, (void *)arg, sizeof(facilities)))
1155                                 return -EFAULT;
1156                         if (sk->state != TCP_LISTEN && sk->state != TCP_CLOSE)
1157                                 return -EINVAL;
1158                         if (facilities.pacsize_in < X25_PS16 || facilities.pacsize_in > X25_PS4096)
1159                                 return -EINVAL;
1160                         if (facilities.pacsize_out < X25_PS16 || facilities.pacsize_out > X25_PS4096)
1161                                 return -EINVAL;
1162                         if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
1163                                 return -EINVAL;
1164                         if (facilities.throughput < 0x03 || facilities.throughput > 0xDD)
1165                                 return -EINVAL;
1166                         if (facilities.reverse != 0 && facilities.reverse != 1)
1167                                 return -EINVAL;
1168                         sk->protinfo.x25->facilities = facilities;
1169                         return 0;
1170                 }
1171 
1172                 case SIOCX25GCALLUSERDATA: {
1173                         struct x25_calluserdata calluserdata;
1174                         calluserdata = sk->protinfo.x25->calluserdata;
1175                         return copy_to_user((void *)arg, &calluserdata, sizeof(calluserdata)) ? -EFAULT : 0;
1176                 }
1177 
1178                 case SIOCX25SCALLUSERDATA: {
1179                         struct x25_calluserdata calluserdata;
1180                         if (copy_from_user(&calluserdata, (void *)arg, sizeof(calluserdata)))
1181                                 return -EFAULT;
1182                         if (calluserdata.cudlength > X25_MAX_CUD_LEN)
1183                                 return -EINVAL;
1184                         sk->protinfo.x25->calluserdata = calluserdata;
1185                         return 0;
1186                 }
1187 
1188                 case SIOCX25GCAUSEDIAG: {
1189                         struct x25_causediag causediag;
1190                         causediag = sk->protinfo.x25->causediag;
1191                         return copy_to_user((void *)arg, &causediag, sizeof(causediag)) ? -EFAULT : 0;
1192                 }
1193 
1194                 default:
1195                         return dev_ioctl(cmd, (void *)arg);
1196         }
1197 
1198         /*NOTREACHED*/
1199         return 0;
1200 }
1201 
1202 static int x25_get_info(char *buffer, char **start, off_t offset, int length)
1203 {
1204         struct sock *s;
1205         struct net_device *dev;
1206         const char *devname;
1207         int len = 0;
1208         off_t pos = 0;
1209         off_t begin = 0;
1210 
1211         cli();
1212 
1213         len += sprintf(buffer, "dest_addr  src_addr   dev   lci st vs vr va   t  t2 t21 t22 t23 Snd-Q Rcv-Q inode\n");
1214 
1215         for (s = x25_list; s != NULL; s = s->next) {
1216                 if (s->protinfo.x25->neighbour == NULL || (dev = s->protinfo.x25->neighbour->dev) == NULL)
1217                         devname = "???";
1218                 else
1219                         devname = s->protinfo.x25->neighbour->dev->name;
1220 
1221                 len += sprintf(buffer + len, "%-10s %-10s %-5s %3.3X  %d  %d  %d  %d %3lu %3lu %3lu %3lu %3lu %5d %5d %ld\n",
1222                         (s->protinfo.x25->dest_addr.x25_addr[0] == '\0')   ? "*" : s->protinfo.x25->dest_addr.x25_addr,
1223                         (s->protinfo.x25->source_addr.x25_addr[0] == '\0') ? "*" : s->protinfo.x25->source_addr.x25_addr,
1224                         devname, 
1225                         s->protinfo.x25->lci & 0x0FFF,
1226                         s->protinfo.x25->state,
1227                         s->protinfo.x25->vs,
1228                         s->protinfo.x25->vr,
1229                         s->protinfo.x25->va,
1230                         x25_display_timer(s) / HZ,
1231                         s->protinfo.x25->t2  / HZ,
1232                         s->protinfo.x25->t21 / HZ,
1233                         s->protinfo.x25->t22 / HZ,
1234                         s->protinfo.x25->t23 / HZ,
1235                         atomic_read(&s->wmem_alloc),
1236                         atomic_read(&s->rmem_alloc),
1237                         s->socket != NULL ? s->socket->inode->i_ino : 0L);
1238 
1239                 pos = begin + len;
1240 
1241                 if (pos < offset) {
1242                         len   = 0;
1243                         begin = pos;
1244                 }
1245 
1246                 if (pos > offset + length)
1247                         break;
1248         }
1249 
1250         sti();
1251 
1252         *start = buffer + (offset - begin);
1253         len   -= (offset - begin);
1254 
1255         if (len > length) len = length;
1256 
1257         return(len);
1258 } 
1259 
1260 struct net_proto_family x25_family_ops = {
1261         AF_X25,
1262         x25_create
1263 };
1264 
1265 static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
1266         family:         AF_X25,
1267 
1268         release:        x25_release,
1269         bind:           x25_bind,
1270         connect:        x25_connect,
1271         socketpair:     sock_no_socketpair,
1272         accept:         x25_accept,
1273         getname:        x25_getname,
1274         poll:           datagram_poll,
1275         ioctl:          x25_ioctl,
1276         listen:         x25_listen,
1277         shutdown:       sock_no_shutdown,
1278         setsockopt:     x25_setsockopt,
1279         getsockopt:     x25_getsockopt,
1280         sendmsg:        x25_sendmsg,
1281         recvmsg:        x25_recvmsg,
1282         mmap:           sock_no_mmap,
1283 };
1284 
1285 #include <linux/smp_lock.h>
1286 SOCKOPS_WRAP(x25_proto, AF_X25);
1287 
1288 
1289 static struct packet_type x25_packet_type =
1290 {
1291         0,              /* MUTTER ntohs(ETH_P_X25),*/
1292         0,              /* copy */
1293         x25_lapb_receive_frame,
1294         NULL,
1295         NULL,
1296 };
1297 
1298 struct notifier_block x25_dev_notifier = {
1299         x25_device_event,
1300         0
1301 };
1302 
1303 void x25_kill_by_neigh(struct x25_neigh *neigh)
1304 {
1305         struct sock *s;
1306 
1307         for( s=x25_list; s != NULL; s=s->next){
1308                 if( s->protinfo.x25->neighbour == neigh )
1309                         x25_disconnect(s, ENETUNREACH, 0, 0);
1310         } 
1311 }
1312 
1313 static int __init x25_init(void)
1314 {
1315 #ifdef MODULE
1316         struct net_device *dev;
1317 #endif /* MODULE */
1318         sock_register(&x25_family_ops);
1319 
1320         x25_packet_type.type = htons(ETH_P_X25);
1321         dev_add_pack(&x25_packet_type);
1322 
1323         register_netdevice_notifier(&x25_dev_notifier);
1324 
1325         printk(KERN_INFO "X.25 for Linux. Version 0.2 for Linux 2.1.15\n");
1326 
1327 #ifdef CONFIG_SYSCTL
1328         x25_register_sysctl();
1329 #endif
1330 
1331         proc_net_create("x25", 0, x25_get_info);
1332         proc_net_create("x25_routes", 0, x25_routes_get_info);
1333 
1334 #ifdef MODULE
1335         /*
1336          *      Register any pre existing devices.
1337          */
1338         read_lock(&dev_base_lock);
1339         for (dev = dev_base; dev != NULL; dev = dev->next) {
1340                 if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25
1341 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
1342                                            || dev->type == ARPHRD_ETHER
1343 #endif
1344                         ))
1345                         x25_link_device_up(dev);
1346         }
1347         read_unlock(&dev_base_lock);
1348 #endif /* MODULE */
1349         return 0;
1350 }
1351 module_init(x25_init);
1352 
1353 
1354 
1355 EXPORT_NO_SYMBOLS;
1356 
1357 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
1358 MODULE_DESCRIPTION("The X.25 Packet Layer network layer protocol");
1359 
1360 static void __exit x25_exit(void)
1361 {
1362 
1363         proc_net_remove("x25");
1364         proc_net_remove("x25_routes");
1365 
1366         x25_link_free();
1367         x25_route_free();
1368 
1369 #ifdef CONFIG_SYSCTL
1370         x25_unregister_sysctl();
1371 #endif
1372 
1373         unregister_netdevice_notifier(&x25_dev_notifier);
1374 
1375         dev_remove_pack(&x25_packet_type);
1376 
1377         sock_unregister(AF_X25);
1378 }
1379 module_exit(x25_exit);
1380 
1381 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.