File: | drivers/net/appletalk/ipddp.c |
Warning: | line 292, column 9 Copies out a struct with uncleared padding (>= 4 bytes) |
1 | /* | |||
2 | * ipddp.c: IP to Appletalk-IP Encapsulation driver for Linux | |||
3 | * Appletalk-IP to IP Decapsulation driver for Linux | |||
4 | * | |||
5 | * Authors: | |||
6 | * - DDP-IP Encap by: Bradford W. Johnson <[email protected]> | |||
7 | * - DDP-IP Decap by: Jay Schulist <[email protected]> | |||
8 | * | |||
9 | * Derived from: | |||
10 | * - Almost all code already existed in net/appletalk/ddp.c I just | |||
11 | * moved/reorginized it into a driver file. Original IP-over-DDP code | |||
12 | * was done by Bradford W. Johnson <[email protected]> | |||
13 | * - skeleton.c: A network driver outline for linux. | |||
14 | * Written 1993-94 by Donald Becker. | |||
15 | * - dummy.c: A dummy net driver. By Nick Holloway. | |||
16 | * - MacGate: A user space Daemon for Appletalk-IP Decap for | |||
17 | * Linux by Jay Schulist <[email protected]> | |||
18 | * | |||
19 | * Copyright 1993 United States Government as represented by the | |||
20 | * Director, National Security Agency. | |||
21 | * | |||
22 | * This software may be used and distributed according to the terms | |||
23 | * of the GNU General Public License, incorporated herein by reference. | |||
24 | */ | |||
25 | ||||
26 | #include <linux1/module.h> | |||
27 | #include <linux1/kernel.h> | |||
28 | #include <linux1/init.h> | |||
29 | #include <linux1/netdevice.h> | |||
30 | #include <linux1/etherdevice.h> | |||
31 | #include <linux1/ip.h> | |||
32 | #include <linux1/atalk.h> | |||
33 | #include <linux1/if_arp.h> | |||
34 | #include <linux1/slab.h> | |||
35 | #include <net/route.h> | |||
36 | #include <asm/uaccess.h> | |||
37 | ||||
38 | #include "ipddp.h" /* Our stuff */ | |||
39 | ||||
40 | static const char version[] = KERN_INFO"\001" "6" "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <[email protected]>\n"; | |||
41 | ||||
42 | static struct ipddp_route *ipddp_route_list; | |||
43 | static DEFINE_SPINLOCK(ipddp_route_lock)spinlock_t ipddp_route_lock = (spinlock_t ) { { .rlock = { .raw_lock = { { (0) } }, .magic = 0xdead4ead, .owner_cpu = -1, .owner = ((void *)-1L), .dep_map = { .name = "ipddp_route_lock" } } } }; | |||
44 | ||||
45 | #ifdef CONFIG_IPDDP_ENCAP1 | |||
46 | static int ipddp_mode = IPDDP_ENCAP1; | |||
47 | #else | |||
48 | static int ipddp_mode = IPDDP_DECAP2; | |||
49 | #endif | |||
50 | ||||
51 | /* Index to functions, as function prototypes. */ | |||
52 | static netdev_tx_t ipddp_xmit(struct sk_buff *skb, | |||
53 | struct net_device *dev); | |||
54 | static int ipddp_create(struct ipddp_route *new_rt); | |||
55 | static int ipddp_delete(struct ipddp_route *rt); | |||
56 | static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt); | |||
57 | static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); | |||
58 | ||||
59 | static const struct net_device_ops ipddp_netdev_ops = { | |||
60 | .ndo_start_xmit = ipddp_xmit, | |||
61 | .ndo_do_ioctl = ipddp_ioctl, | |||
62 | .ndo_change_mtu = eth_change_mtu, | |||
63 | .ndo_set_mac_address = eth_mac_addr, | |||
64 | .ndo_validate_addr = eth_validate_addr, | |||
65 | }; | |||
66 | ||||
67 | static struct net_device * __init__attribute__ ((__section__(".init.text"))) __attribute__((no_instrument_function )) ipddp_init(void) | |||
68 | { | |||
69 | static unsigned version_printed; | |||
70 | struct net_device *dev; | |||
71 | int err; | |||
72 | ||||
73 | dev = alloc_etherdev(0)alloc_etherdev_mqs(0, 1, 1); | |||
74 | if (!dev) | |||
75 | return ERR_PTR(-ENOMEM12); | |||
76 | ||||
77 | netif_keep_dst(dev); | |||
78 | strcpy(dev->name, "ipddp%d"); | |||
79 | ||||
80 | if (version_printed++ == 0) | |||
81 | printk(version); | |||
82 | ||||
83 | /* Initialize the device structure. */ | |||
84 | dev->netdev_ops = &ipddp_netdev_ops; | |||
85 | ||||
86 | dev->type = ARPHRD_IPDDP777; /* IP over DDP tunnel */ | |||
87 | dev->mtu = 585; | |||
88 | dev->flags |= IFF_NOARPIFF_NOARP; | |||
89 | ||||
90 | /* | |||
91 | * The worst case header we will need is currently a | |||
92 | * ethernet header (14 bytes) and a ddp header (sizeof ddpehdr+1) | |||
93 | * We send over SNAP so that takes another 8 bytes. | |||
94 | */ | |||
95 | dev->hard_header_len = 14+8+sizeof(struct ddpehdr)+1; | |||
96 | ||||
97 | err = register_netdev(dev); | |||
98 | if (err) { | |||
99 | free_netdev(dev); | |||
100 | return ERR_PTR(err); | |||
101 | } | |||
102 | ||||
103 | /* Let the user now what mode we are in */ | |||
104 | if(ipddp_mode == IPDDP_ENCAP1) | |||
105 | printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <[email protected]>\n", | |||
106 | dev->name); | |||
107 | if(ipddp_mode == IPDDP_DECAP2) | |||
108 | printk("%s: Appletalk-IP Decap. mode by Jay Schulist <[email protected]>\n", | |||
109 | dev->name); | |||
110 | ||||
111 | return dev; | |||
112 | } | |||
113 | ||||
114 | ||||
115 | /* | |||
116 | * Transmit LLAP/ELAP frame using aarp_send_ddp. | |||
117 | */ | |||
118 | static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev) | |||
119 | { | |||
120 | __be32 paddr = skb_rtable(skb)->rt_gateway; | |||
121 | struct ddpehdr *ddp; | |||
122 | struct ipddp_route *rt; | |||
123 | struct atalk_addr *our_addr; | |||
124 | ||||
125 | spin_lock(&ipddp_route_lock); | |||
126 | ||||
127 | /* | |||
128 | * Find appropriate route to use, based only on IP number. | |||
129 | */ | |||
130 | for(rt = ipddp_route_list; rt != NULL((void *)0); rt = rt->next) | |||
131 | { | |||
132 | if(rt->ip == paddr) | |||
133 | break; | |||
134 | } | |||
135 | if(rt == NULL((void *)0)) { | |||
136 | spin_unlock(&ipddp_route_lock); | |||
137 | return NETDEV_TX_OK; | |||
138 | } | |||
139 | ||||
140 | our_addr = atalk_find_dev_addr(rt->dev); | |||
141 | ||||
142 | if(ipddp_mode == IPDDP_DECAP2) | |||
143 | /* | |||
144 | * Pull off the excess room that should not be there. | |||
145 | * This is due to a hard-header problem. This is the | |||
146 | * quick fix for now though, till it breaks. | |||
147 | */ | |||
148 | skb_pull(skb, 35-(sizeof(struct ddpehdr)+1)); | |||
149 | ||||
150 | /* Create the Extended DDP header */ | |||
151 | ddp = (struct ddpehdr *)skb->data; | |||
152 | ddp->deh_len_hops = htons(skb->len + (1<<10))(( __be16)(__builtin_constant_p((__u16)((skb->len + (1<< 10)))) ? ((__u16)( (((__u16)((skb->len + (1<<10))) & (__u16)0x00ffU) << 8) | (((__u16)((skb->len + (1<< 10))) & (__u16)0xff00U) >> 8))) : __fswab16((skb-> len + (1<<10))))); | |||
153 | ddp->deh_sum = 0; | |||
154 | ||||
155 | /* | |||
156 | * For Localtalk we need aarp_send_ddp to strip the | |||
157 | * long DDP header and place a shot DDP header on it. | |||
158 | */ | |||
159 | if(rt->dev->type == ARPHRD_LOCALTLK773) | |||
160 | { | |||
161 | ddp->deh_dnet = 0; /* FIXME more hops?? */ | |||
162 | ddp->deh_snet = 0; | |||
163 | } | |||
164 | else | |||
165 | { | |||
166 | ddp->deh_dnet = rt->at.s_net; /* FIXME more hops?? */ | |||
167 | ddp->deh_snet = our_addr->s_net; | |||
168 | } | |||
169 | ddp->deh_dnode = rt->at.s_node; | |||
170 | ddp->deh_snode = our_addr->s_node; | |||
171 | ddp->deh_dport = 72; | |||
172 | ddp->deh_sport = 72; | |||
173 | ||||
174 | *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ | |||
175 | ||||
176 | skb->protocol = htons(ETH_P_ATALK)(( __be16)(__builtin_constant_p((__u16)((0x809B))) ? ((__u16) ( (((__u16)((0x809B)) & (__u16)0x00ffU) << 8) | ((( __u16)((0x809B)) & (__u16)0xff00U) >> 8))) : __fswab16 ((0x809B)))); /* Protocol has changed */ | |||
177 | ||||
178 | dev->stats.tx_packets++; | |||
179 | dev->stats.tx_bytes += skb->len; | |||
180 | ||||
181 | aarp_send_ddp(rt->dev, skb, &rt->at, NULL((void *)0)); | |||
182 | ||||
183 | spin_unlock(&ipddp_route_lock); | |||
184 | ||||
185 | return NETDEV_TX_OK; | |||
186 | } | |||
187 | ||||
188 | /* | |||
189 | * Create a routing entry. We first verify that the | |||
190 | * record does not already exist. If it does we return -EEXIST | |||
191 | */ | |||
192 | static int ipddp_create(struct ipddp_route *new_rt) | |||
193 | { | |||
194 | struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL((( gfp_t)(0x400000u|0x2000000u)) | (( gfp_t)0x40u) | (( gfp_t )0x80u))); | |||
195 | ||||
196 | if (rt == NULL((void *)0)) | |||
197 | return -ENOMEM12; | |||
198 | ||||
199 | rt->ip = new_rt->ip; | |||
200 | rt->at = new_rt->at; | |||
201 | rt->next = NULL((void *)0); | |||
202 | if ((rt->dev = atrtr_get_dev(&rt->at)) == NULL((void *)0)) { | |||
203 | kfree(rt); | |||
204 | return -ENETUNREACH101; | |||
205 | } | |||
206 | ||||
207 | spin_lock_bh(&ipddp_route_lock); | |||
208 | if (__ipddp_find_route(rt)) { | |||
209 | spin_unlock_bh(&ipddp_route_lock); | |||
210 | kfree(rt); | |||
211 | return -EEXIST17; | |||
212 | } | |||
213 | ||||
214 | rt->next = ipddp_route_list; | |||
215 | ipddp_route_list = rt; | |||
216 | ||||
217 | spin_unlock_bh(&ipddp_route_lock); | |||
218 | ||||
219 | return 0; | |||
220 | } | |||
221 | ||||
222 | /* | |||
223 | * Delete a route, we only delete a FULL match. | |||
224 | * If route does not exist we return -ENOENT. | |||
225 | */ | |||
226 | static int ipddp_delete(struct ipddp_route *rt) | |||
227 | { | |||
228 | struct ipddp_route **r = &ipddp_route_list; | |||
229 | struct ipddp_route *tmp; | |||
230 | ||||
231 | spin_lock_bh(&ipddp_route_lock); | |||
232 | while((tmp = *r) != NULL((void *)0)) | |||
233 | { | |||
234 | if(tmp->ip == rt->ip && | |||
235 | tmp->at.s_net == rt->at.s_net && | |||
236 | tmp->at.s_node == rt->at.s_node) | |||
237 | { | |||
238 | *r = tmp->next; | |||
239 | spin_unlock_bh(&ipddp_route_lock); | |||
240 | kfree(tmp); | |||
241 | return 0; | |||
242 | } | |||
243 | r = &tmp->next; | |||
244 | } | |||
245 | ||||
246 | spin_unlock_bh(&ipddp_route_lock); | |||
247 | return -ENOENT2; | |||
248 | } | |||
249 | ||||
250 | /* | |||
251 | * Find a routing entry, we only return a FULL match | |||
252 | */ | |||
253 | static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt) | |||
254 | { | |||
255 | struct ipddp_route *f; | |||
256 | ||||
257 | for(f = ipddp_route_list; f != NULL((void *)0); f = f->next) | |||
258 | { | |||
259 | if(f->ip == rt->ip && | |||
260 | f->at.s_net == rt->at.s_net && | |||
261 | f->at.s_node == rt->at.s_node) | |||
262 | return f; | |||
263 | } | |||
264 | ||||
265 | return NULL((void *)0); | |||
266 | } | |||
267 | ||||
268 | static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
269 | { | |||
270 | struct ipddp_route __user *rt = ifr->ifr_dataifr_ifru.ifru_data; | |||
271 | struct ipddp_route rcp, rcp2, *rp; | |||
272 | ||||
273 | if(!capable(CAP_NET_ADMIN12)) | |||
| ||||
274 | return -EPERM1; | |||
275 | ||||
276 | if(copy_from_user(&rcp, rt, sizeof(rcp))) | |||
277 | return -EFAULT14; | |||
278 | ||||
279 | switch(cmd) | |||
280 | { | |||
281 | case SIOCADDIPDDPRT(0x89F0): | |||
282 | return ipddp_create(&rcp); | |||
283 | ||||
284 | case SIOCFINDIPDDPRT(0x89F0 +2): | |||
285 | spin_lock_bh(&ipddp_route_lock); | |||
286 | rp = __ipddp_find_route(&rcp); | |||
287 | if (rp) | |||
288 | memcpy(&rcp2, rp, sizeof(rcp2))({ size_t __len = (sizeof(rcp2)); void *__ret; if (__builtin_constant_p (sizeof(rcp2)) && __len >= 64) __ret = __memcpy((& rcp2), (rp), __len); else __ret = __builtin_memcpy((&rcp2 ), (rp), __len); __ret; }); | |||
289 | spin_unlock_bh(&ipddp_route_lock); | |||
290 | ||||
291 | if (rp) { | |||
292 | if (copy_to_user(rt, &rcp2, | |||
| ||||
293 | sizeof(struct ipddp_route))) | |||
294 | return -EFAULT14; | |||
295 | return 0; | |||
296 | } else | |||
297 | return -ENOENT2; | |||
298 | ||||
299 | case SIOCDELIPDDPRT(0x89F0 +1): | |||
300 | return ipddp_delete(&rcp); | |||
301 | ||||
302 | default: | |||
303 | return -EINVAL22; | |||
304 | } | |||
305 | } | |||
306 | ||||
307 | static struct net_device *dev_ipddp; | |||
308 | ||||
309 | MODULE_LICENSE("GPL")struct __UNIQUE_ID_license54 {}; | |||
310 | module_param(ipddp_mode, int, 0)static inline __attribute__((no_instrument_function)) int __attribute__ ((unused)) *__check_ipddp_mode(void) { return(&(ipddp_mode )); }; static const char __param_str_ipddp_mode[] = "ipddp" "." "ipddp_mode"; static struct kernel_param const __param_ipddp_mode __attribute__((__used__)) __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) = { __param_str_ipddp_mode , ((struct module *)0), ¶m_ops_int, ((sizeof(struct { int:-!!((0) < 0); })) + (sizeof(struct { int:-!!((0) > 0777); })) + (sizeof(struct { int:-!!((((0) >> 6) & 4) < (((0) >> 3) & 4)); })) + (sizeof(struct { int :-!!((((0) >> 3) & 4) < ((0) & 4)); })) + (sizeof (struct { int:-!!((((0) >> 6) & 2) < (((0) >> 3) & 2)); })) + (sizeof(struct { int:-!!((0) & 2); } )) + (0)), -1, 0, { &ipddp_mode } }; struct __UNIQUE_ID_ipddp_modetype55 {}; | |||
311 | ||||
312 | static int __init__attribute__ ((__section__(".init.text"))) __attribute__((no_instrument_function )) ipddp_init_module(void) | |||
313 | { | |||
314 | dev_ipddp = ipddp_init(); | |||
315 | if (IS_ERR(dev_ipddp)) | |||
316 | return PTR_ERR(dev_ipddp); | |||
317 | return 0; | |||
318 | } | |||
319 | ||||
320 | static void __exit__attribute__ ((__section__(".exit.text"))) __attribute__((__used__ )) __attribute__((no_instrument_function)) ipddp_cleanup_module(void) | |||
321 | { | |||
322 | struct ipddp_route *p; | |||
323 | ||||
324 | unregister_netdev(dev_ipddp); | |||
325 | free_netdev(dev_ipddp); | |||
326 | ||||
327 | while (ipddp_route_list) { | |||
328 | p = ipddp_route_list->next; | |||
329 | kfree(ipddp_route_list); | |||
330 | ipddp_route_list = p; | |||
331 | } | |||
332 | } | |||
333 | ||||
334 | module_init(ipddp_init_module)static initcall_t __initcall_ipddp_init_module6 __attribute__ ((__used__)) __attribute__((__section__(".initcall" "6" ".init" ))) = ipddp_init_module;;; | |||
335 | module_exit(ipddp_cleanup_module)static exitcall_t __exitcall_ipddp_cleanup_module __attribute__ ((__used__)) __attribute__ ((__section__(".exitcall.exit"))) = ipddp_cleanup_module;; |