File: /usr/src/linux/net/ax25/ax25_uid.c

1     /*
2      *	AX.25 release 037
3      *
4      *	This code REQUIRES 2.1.15 or higher/ NET3.038
5      *
6      *	This module:
7      *		This module is free software; you can redistribute it and/or
8      *		modify it under the terms of the GNU General Public License
9      *		as published by the Free Software Foundation; either version
10      *		2 of the License, or (at your option) any later version.
11      *
12      *	History
13      *	AX.25 036	Jonathan(G4KLX)	Split from af_ax25.c.
14      */
15     
16     #include <linux/errno.h>
17     #include <linux/types.h>
18     #include <linux/socket.h>
19     #include <linux/in.h>
20     #include <linux/kernel.h>
21     #include <linux/sched.h>
22     #include <linux/timer.h>
23     #include <linux/string.h>
24     #include <linux/sockios.h>
25     #include <linux/net.h>
26     #include <net/ax25.h>
27     #include <linux/inet.h>
28     #include <linux/netdevice.h>
29     #include <linux/if_arp.h>
30     #include <linux/skbuff.h>
31     #include <net/sock.h>
32     #include <asm/uaccess.h>
33     #include <asm/system.h>
34     #include <linux/fcntl.h>
35     #include <linux/mm.h>
36     #include <linux/interrupt.h>
37     #include <linux/notifier.h>
38     #include <linux/proc_fs.h>
39     #include <linux/stat.h>
40     #include <linux/netfilter.h>
41     #include <linux/sysctl.h>
42     #include <net/ip.h>
43     #include <net/arp.h>
44     
45     /*
46      *	Callsign/UID mapper. This is in kernel space for security on multi-amateur machines.
47      */
48     
49     static ax25_uid_assoc *ax25_uid_list;
50     
51     int ax25_uid_policy = 0;
52     
53     ax25_address *ax25_findbyuid(uid_t uid)
54     {
55     	ax25_uid_assoc *ax25_uid;
56     
57     	for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
58     		if (ax25_uid->uid == uid)
59     			return &ax25_uid->call;
60     	}
61     
62     	return NULL;
63     }
64     
65     int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
66     {
67     	ax25_uid_assoc *s, *ax25_uid;
68     	unsigned long flags;
69     
70     	switch (cmd) {
71     		case SIOCAX25GETUID:
72     			for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
73     				if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
74     					return ax25_uid->uid;
75     			}
76     			return -ENOENT;
77     
78     		case SIOCAX25ADDUID:
79     			if (!capable(CAP_NET_ADMIN))
80     				return -EPERM;
81     			if (ax25_findbyuid(sax->sax25_uid))
82     				return -EEXIST;
83     			if (sax->sax25_uid == 0)
84     				return -EINVAL;
85     			if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
86     				return -ENOMEM;
87     			ax25_uid->uid  = sax->sax25_uid;
88     			ax25_uid->call = sax->sax25_call;
89     			save_flags(flags); cli();
90     			ax25_uid->next = ax25_uid_list;
91     			ax25_uid_list  = ax25_uid;
92     			restore_flags(flags);
93     			return 0;
94     
95     		case SIOCAX25DELUID:
96     			if (!capable(CAP_NET_ADMIN))
97     				return -EPERM;
98     			for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
99     				if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
100     					break;
101     			}
102     			if (ax25_uid == NULL)
103     				return -ENOENT;
104     			save_flags(flags); cli();
105     			if ((s = ax25_uid_list) == ax25_uid) {
106     				ax25_uid_list = s->next;
107     				restore_flags(flags);
108     				kfree(ax25_uid);
109     				return 0;
110     			}
111     			while (s != NULL && s->next != NULL) {
112     				if (s->next == ax25_uid) {
113     					s->next = ax25_uid->next;
114     					restore_flags(flags);
115     					kfree(ax25_uid);
116     					return 0;
117     				}
118     				s = s->next;
119     			}
120     			restore_flags(flags);
121     			return -ENOENT;
122     
123     		default:
124     			return -EINVAL;
125     	}
126     
127     	return -EINVAL;	/*NOTREACHED */
128     }
129     
130     int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
131     {
132     	ax25_uid_assoc *pt;
133     	int len     = 0;
134     	off_t pos   = 0;
135     	off_t begin = 0;
136     
137     	cli();
138     
139     	len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
140     
141     	for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
142     		len += sprintf(buffer + len, "%6d %s\n", pt->uid, ax2asc(&pt->call));
143     
144     		pos = begin + len;
145     
146     		if (pos < offset) {
147     			len = 0;
148     			begin = pos;
149     		}
150     
151     		if (pos > offset + length)
152     			break;
153     	}
154     
155     	sti();
156     
157     	*start = buffer + (offset - begin);
158     	len   -= offset - begin;
159     
160     	if (len > length) len = length;
161     
162     	return len;
163     }
164     
165     /*
166      *	Free all memory associated with UID/Callsign structures.
167      */
168     void __exit ax25_uid_free(void)
169     {
170     	ax25_uid_assoc *s, *ax25_uid = ax25_uid_list;
171     
172     	while (ax25_uid != NULL) {
173     		s        = ax25_uid;
174     		ax25_uid = ax25_uid->next;
175     
176     		kfree(s);
177     	}
178     }
179