2005-04-16 15:20:36 -07:00
/*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* Copyright ( C ) Jonathan Naylor G4KLX ( g4klx @ g4klx . demon . co . uk )
*/
2006-01-11 12:17:47 -08:00
# include <linux/capability.h>
2005-04-16 15:20:36 -07:00
# include <linux/errno.h>
# include <linux/types.h>
# include <linux/socket.h>
# include <linux/in.h>
# include <linux/kernel.h>
# include <linux/timer.h>
# include <linux/string.h>
# include <linux/sockios.h>
# include <linux/net.h>
# include <linux/spinlock.h>
# include <net/ax25.h>
# include <linux/inet.h>
# include <linux/netdevice.h>
# include <linux/if_arp.h>
# include <linux/skbuff.h>
# include <net/sock.h>
# include <asm/uaccess.h>
# include <asm/system.h>
# include <linux/fcntl.h>
# include <linux/mm.h>
# include <linux/interrupt.h>
2005-08-23 10:11:45 -07:00
# include <linux/list.h>
2005-04-16 15:20:36 -07:00
# include <linux/notifier.h>
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
# include <linux/stat.h>
# include <linux/netfilter.h>
# include <linux/sysctl.h>
# include <net/ip.h>
# include <net/arp.h>
/*
* Callsign / UID mapper . This is in kernel space for security on multi - amateur machines .
*/
2005-08-23 10:11:45 -07:00
HLIST_HEAD ( ax25_uid_list ) ;
2005-04-16 15:20:36 -07:00
static DEFINE_RWLOCK ( ax25_uid_lock ) ;
int ax25_uid_policy = 0 ;
2006-05-03 23:25:17 -07:00
EXPORT_SYMBOL ( ax25_uid_policy ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_assoc * ax25_findbyuid ( uid_t uid )
2005-04-16 15:20:36 -07:00
{
2005-08-23 10:11:45 -07:00
ax25_uid_assoc * ax25_uid , * res = NULL ;
struct hlist_node * node ;
2005-04-16 15:20:36 -07:00
read_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_for_each ( ax25_uid , node , & ax25_uid_list ) {
2005-04-16 15:20:36 -07:00
if ( ax25_uid - > uid = = uid ) {
2005-08-23 10:11:45 -07:00
ax25_uid_hold ( ax25_uid ) ;
res = ax25_uid ;
2005-04-16 15:20:36 -07:00
break ;
}
}
read_unlock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
return res ;
2005-04-16 15:20:36 -07:00
}
2006-05-03 23:25:17 -07:00
EXPORT_SYMBOL ( ax25_findbyuid ) ;
2005-04-16 15:20:36 -07:00
int ax25_uid_ioctl ( int cmd , struct sockaddr_ax25 * sax )
{
2005-08-23 10:11:45 -07:00
ax25_uid_assoc * ax25_uid ;
struct hlist_node * node ;
ax25_uid_assoc * user ;
2005-04-16 15:20:36 -07:00
unsigned long res ;
switch ( cmd ) {
case SIOCAX25GETUID :
res = - ENOENT ;
read_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_for_each ( ax25_uid , node , & ax25_uid_list ) {
2005-04-16 15:20:36 -07:00
if ( ax25cmp ( & sax - > sax25_call , & ax25_uid - > call ) = = 0 ) {
res = ax25_uid - > uid ;
break ;
}
}
read_unlock ( & ax25_uid_lock ) ;
return res ;
case SIOCAX25ADDUID :
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
2005-08-23 10:11:45 -07:00
user = ax25_findbyuid ( sax - > sax25_uid ) ;
if ( user ) {
ax25_uid_put ( user ) ;
2005-04-16 15:20:36 -07:00
return - EEXIST ;
2005-08-23 10:11:45 -07:00
}
2005-04-16 15:20:36 -07:00
if ( sax - > sax25_uid = = 0 )
return - EINVAL ;
if ( ( ax25_uid = kmalloc ( sizeof ( * ax25_uid ) , GFP_KERNEL ) ) = = NULL )
return - ENOMEM ;
2005-08-23 10:11:45 -07:00
atomic_set ( & ax25_uid - > refcount , 1 ) ;
2005-04-16 15:20:36 -07:00
ax25_uid - > uid = sax - > sax25_uid ;
ax25_uid - > call = sax - > sax25_call ;
write_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
hlist_add_head ( & ax25_uid - > uid_node , & ax25_uid_list ) ;
2005-04-16 15:20:36 -07:00
write_unlock ( & ax25_uid_lock ) ;
return 0 ;
case SIOCAX25DELUID :
if ( ! capable ( CAP_NET_ADMIN ) )
return - EPERM ;
2005-08-23 10:11:45 -07:00
ax25_uid = NULL ;
2005-04-16 15:20:36 -07:00
write_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_for_each ( ax25_uid , node , & ax25_uid_list ) {
if ( ax25cmp ( & sax - > sax25_call , & ax25_uid - > call ) = = 0 )
2005-04-16 15:20:36 -07:00
break ;
}
if ( ax25_uid = = NULL ) {
write_unlock ( & ax25_uid_lock ) ;
return - ENOENT ;
}
2005-08-23 10:11:45 -07:00
hlist_del_init ( & ax25_uid - > uid_node ) ;
ax25_uid_put ( ax25_uid ) ;
2005-04-16 15:20:36 -07:00
write_unlock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
default :
return - EINVAL ;
}
return - EINVAL ; /*NOTREACHED */
}
# ifdef CONFIG_PROC_FS
static void * ax25_uid_seq_start ( struct seq_file * seq , loff_t * pos )
{
struct ax25_uid_assoc * pt ;
2005-08-23 10:11:45 -07:00
struct hlist_node * node ;
int i = 0 ;
2005-04-16 15:20:36 -07:00
read_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_for_each ( pt , node , & ax25_uid_list ) {
2005-04-16 15:20:36 -07:00
if ( i = = * pos )
return pt ;
+ + i ;
}
return NULL ;
}
static void * ax25_uid_seq_next ( struct seq_file * seq , void * v , loff_t * pos )
{
+ + * pos ;
2005-08-23 10:11:45 -07:00
return hlist_entry ( ( ( ax25_uid_assoc * ) v ) - > uid_node . next ,
2007-02-09 23:24:31 +09:00
ax25_uid_assoc , uid_node ) ;
2005-04-16 15:20:36 -07:00
}
static void ax25_uid_seq_stop ( struct seq_file * seq , void * v )
{
read_unlock ( & ax25_uid_lock ) ;
}
static int ax25_uid_seq_show ( struct seq_file * seq , void * v )
{
2005-09-06 15:49:39 -07:00
char buf [ 11 ] ;
2005-04-16 15:20:36 -07:00
if ( v = = SEQ_START_TOKEN )
seq_printf ( seq , " Policy: %d \n " , ax25_uid_policy ) ;
else {
struct ax25_uid_assoc * pt = v ;
2005-09-06 15:49:39 -07:00
seq_printf ( seq , " %6d %s \n " , pt - > uid , ax2asc ( buf , & pt - > call ) ) ;
2005-04-16 15:20:36 -07:00
}
return 0 ;
}
static struct seq_operations ax25_uid_seqops = {
. start = ax25_uid_seq_start ,
. next = ax25_uid_seq_next ,
. stop = ax25_uid_seq_stop ,
. show = ax25_uid_seq_show ,
} ;
static int ax25_uid_info_open ( struct inode * inode , struct file * file )
{
return seq_open ( file , & ax25_uid_seqops ) ;
}
2007-02-12 00:55:35 -08:00
const struct file_operations ax25_uid_fops = {
2005-04-16 15:20:36 -07:00
. owner = THIS_MODULE ,
. open = ax25_uid_info_open ,
. read = seq_read ,
. llseek = seq_lseek ,
. release = seq_release ,
} ;
# endif
/*
* Free all memory associated with UID / Callsign structures .
*/
void __exit ax25_uid_free ( void )
{
2005-08-23 10:11:45 -07:00
ax25_uid_assoc * ax25_uid ;
struct hlist_node * node ;
2005-04-16 15:20:36 -07:00
write_lock ( & ax25_uid_lock ) ;
2005-08-23 10:11:45 -07:00
ax25_uid_for_each ( ax25_uid , node , & ax25_uid_list ) {
hlist_del_init ( & ax25_uid - > uid_node ) ;
ax25_uid_put ( ax25_uid ) ;
2005-04-16 15:20:36 -07:00
}
write_unlock ( & ax25_uid_lock ) ;
}