blob: 8b98d53d99764be297362969fc1c88d1865639ec [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, network interfaces and related functions (linklevel).
4 *
5 * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
Joe Perches475be4d2012-02-19 19:52:38 -080012 * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * guy@traverse.com.au
14 * Outgoing calls - looks for a 'V' in first char of dialed number
15 * Incoming calls - checks first character of eaz as follows:
16 * Numeric - accept DATA only - original functionality
17 * 'V' - accept VOICE (DOV) only
18 * 'B' - accept BOTH DATA and DOV types
19 *
20 * Jan 2001: fix CISCO HDLC Bjoern A. Zeeb <i4l@zabbadoz.net>
Joe Perches475be4d2012-02-19 19:52:38 -080021 * for info on the protocol, see
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
23 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/isdn.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <net/arp.h>
28#include <net/dst.h>
29#include <net/pkt_sched.h>
30#include <linux/inetdevice.h>
31#include "isdn_common.h"
32#include "isdn_net.h"
33#ifdef CONFIG_ISDN_PPP
34#include "isdn_ppp.h"
35#endif
36#ifdef CONFIG_ISDN_X25
37#include <linux/concap.h>
38#include "isdn_concap.h"
39#endif
40
41
42/*
Joe Perches475be4d2012-02-19 19:52:38 -080043 * Outline of new tbusy handling:
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 *
45 * Old method, roughly spoken, consisted of setting tbusy when entering
46 * isdn_net_start_xmit() and at several other locations and clearing
47 * it from isdn_net_start_xmit() thread when sending was successful.
48 *
49 * With 2.3.x multithreaded network core, to prevent problems, tbusy should
50 * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
51 * condition is detected. Other threads (in particular isdn_net_stat_callb())
52 * are only allowed to clear tbusy.
53 *
54 * -HE
55 */
56
57/*
58 * About SOFTNET:
59 * Most of the changes were pretty obvious and basically done by HE already.
60 *
61 * One problem of the isdn net device code is that is uses struct net_device
Joe Perches475be4d2012-02-19 19:52:38 -080062 * for masters and slaves. However, only master interface are registered to
63 * the network layer, and therefore, it only makes sense to call netif_*
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 * functions on them.
65 *
66 * --KG
67 */
68
Joe Perches475be4d2012-02-19 19:52:38 -080069/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 * Find out if the netdevice has been ifup-ed yet.
71 * For slaves, look at the corresponding master.
72 */
73static __inline__ int isdn_net_device_started(isdn_net_dev *n)
74{
75 isdn_net_local *lp = n->local;
76 struct net_device *dev;
Joe Perches475be4d2012-02-19 19:52:38 -080077
78 if (lp->master)
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 dev = lp->master;
80 else
Karsten Keild62a38d2007-10-08 20:37:11 -070081 dev = n->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 return netif_running(dev);
83}
84
85/*
86 * wake up the network -> net_device queue.
87 * For slaves, wake the corresponding master interface.
88 */
89static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
90{
Joe Perches475be4d2012-02-19 19:52:38 -080091 if (lp->master)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 netif_wake_queue(lp->master);
93 else
Karsten Keild62a38d2007-10-08 20:37:11 -070094 netif_wake_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095}
96
97/*
98 * stop the network -> net_device queue.
99 * For slaves, stop the corresponding master interface.
100 */
101static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
102{
103 if (lp->master)
104 netif_stop_queue(lp->master);
105 else
Karsten Keild62a38d2007-10-08 20:37:11 -0700106 netif_stop_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107}
108
109/*
110 * find out if the net_device which this lp belongs to (lp can be
Joe Perches475be4d2012-02-19 19:52:38 -0800111 * master or slave) is busy. It's busy iff all (master and slave)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * queues are busy
113 */
114static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
115{
116 isdn_net_local *nlp;
117 isdn_net_dev *nd;
118 unsigned long flags;
119
120 if (!isdn_net_lp_busy(lp))
121 return 0;
122
123 if (lp->master)
Wang Chen838361f2008-12-03 15:49:46 -0800124 nd = ISDN_MASTER_PRIV(lp)->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 else
126 nd = lp->netdev;
Joe Perches475be4d2012-02-19 19:52:38 -0800127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 spin_lock_irqsave(&nd->queue_lock, flags);
129 nlp = lp->next;
130 while (nlp != lp) {
131 if (!isdn_net_lp_busy(nlp)) {
132 spin_unlock_irqrestore(&nd->queue_lock, flags);
133 return 0;
134 }
135 nlp = nlp->next;
136 }
137 spin_unlock_irqrestore(&nd->queue_lock, flags);
138 return 1;
139}
140
141static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
142{
143 atomic_inc(&lp->frame_cnt);
144 if (isdn_net_device_busy(lp))
145 isdn_net_device_stop_queue(lp);
146}
147
148static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
149{
150 atomic_dec(&lp->frame_cnt);
151
152 if (!(isdn_net_device_busy(lp))) {
153 if (!skb_queue_empty(&lp->super_tx_queue)) {
154 schedule_work(&lp->tqueue);
155 } else {
156 isdn_net_device_wake_queue(lp);
157 }
Joe Perches475be4d2012-02-19 19:52:38 -0800158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
161static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
162{
163 atomic_set(&lp->frame_cnt, 0);
164}
165
Joe Perches475be4d2012-02-19 19:52:38 -0800166/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 * to be safe.
168 * For 2.3.x we push it up to 20 secs, because call establishment
Joe Perches475be4d2012-02-19 19:52:38 -0800169 * (in particular callback) may take such a long time, and we
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 * don't want confusing messages in the log. However, there is a slight
171 * possibility that this large timeout will break other things like MPPP,
172 * which might rely on the tx timeout. If so, we'll find out this way...
173 */
174
Joe Perches475be4d2012-02-19 19:52:38 -0800175#define ISDN_NET_TX_TIMEOUT (20 * HZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
177/* Prototypes */
178
Adrian Bunk3e206b02005-06-25 14:58:35 -0700179static int isdn_net_force_dial_lp(isdn_net_local *);
Stephen Hemminger8b62ff22009-08-31 19:50:44 +0000180static netdev_tx_t isdn_net_start_xmit(struct sk_buff *,
Joe Perches475be4d2012-02-19 19:52:38 -0800181 struct net_device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
184static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
185
186char *isdn_net_revision = "$Revision: 1.1.2.2 $";
187
Joe Perches475be4d2012-02-19 19:52:38 -0800188/*
189 * Code for raw-networking over ISDN
190 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192static void
193isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
194{
Joe Perches475be4d2012-02-19 19:52:38 -0800195 if (skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 u_short proto = ntohs(skb->protocol);
198
199 printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
200 dev->name,
201 (reason != NULL) ? reason : "unknown",
202 (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
Joe Perches475be4d2012-02-19 19:52:38 -0800203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 dst_link_failure(skb);
205 }
206 else { /* dial not triggered by rawIP packet */
207 printk(KERN_DEBUG "isdn_net: %s: %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800208 dev->name,
209 (reason != NULL) ? reason : "reason unknown");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 }
211}
212
213static void
214isdn_net_reset(struct net_device *dev)
215{
216#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800217 struct concap_device_ops *dops =
218 ((isdn_net_local *)netdev_priv(dev))->dops;
219 struct concap_proto *cprot =
220 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221#endif
222#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800223 if (cprot && cprot->pops && dops)
224 cprot->pops->restart(cprot, dev, dops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225#endif
226}
227
228/* Open/initialize the board. */
229static int
230isdn_net_open(struct net_device *dev)
231{
232 int i;
233 struct net_device *p;
234 struct in_device *in_dev;
235
236 /* moved here from isdn_net_reset, because only the master has an
237 interface associated which is supposed to be started. BTW:
238 we need to call netif_start_queue, not netif_wake_queue here */
239 netif_start_queue(dev);
240
241 isdn_net_reset(dev);
242 /* Fill in the MAC-level header (not needed, but for compatibility... */
243 for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
244 dev->dev_addr[i] = 0xfc;
245 if ((in_dev = dev->ip_ptr) != NULL) {
246 /*
247 * Any address will do - we take the first
248 */
249 struct in_ifaddr *ifa = in_dev->ifa_list;
250 if (ifa != NULL)
Joe Perches475be4d2012-02-19 19:52:38 -0800251 memcpy(dev->dev_addr + 2, &ifa->ifa_local, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
253
254 /* If this interface has slaves, start them also */
Wang Chen838361f2008-12-03 15:49:46 -0800255 p = MASTER_TO_SLAVE(dev);
256 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 while (p) {
258 isdn_net_reset(p);
Wang Chen838361f2008-12-03 15:49:46 -0800259 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 }
261 }
262 isdn_lock_drivers();
263 return 0;
264}
265
266/*
267 * Assign an ISDN-channel to a net-interface
268 */
269static void
Joe Perches475be4d2012-02-19 19:52:38 -0800270isdn_net_bind_channel(isdn_net_local *lp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 lp->flags |= ISDN_NET_CONNECTED;
273 lp->isdn_device = dev->drvmap[idx];
274 lp->isdn_channel = dev->chanmap[idx];
275 dev->rx_netdev[idx] = lp->netdev;
276 dev->st_netdev[idx] = lp->netdev;
277}
278
279/*
280 * unbind a net-interface (resets interface after an error)
281 */
282static void
Joe Perches475be4d2012-02-19 19:52:38 -0800283isdn_net_unbind_channel(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{
285 skb_queue_purge(&lp->super_tx_queue);
286
287 if (!lp->master) { /* reset only master device */
288 /* Moral equivalent of dev_purge_queues():
289 BEWARE! This chunk of code cannot be called from hardware
290 interrupt handler. I hope it is true. --ANK
Joe Perches475be4d2012-02-19 19:52:38 -0800291 */
David S. Miller5aa70992008-07-08 22:59:10 -0700292 qdisc_reset_all_tx(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294 lp->dialstate = 0;
295 dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
296 dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
Paul Bollebae58432009-01-14 14:41:00 -0800297 if (lp->isdn_device != -1 && lp->isdn_channel != -1)
298 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
299 ISDN_USAGE_NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 lp->flags &= ~ISDN_NET_CONNECTED;
301 lp->isdn_device = -1;
302 lp->isdn_channel = -1;
303}
304
305/*
306 * Perform auto-hangup and cps-calculation for net-interfaces.
307 *
308 * auto-hangup:
309 * Increment idle-counter (this counter is reset on any incoming or
310 * outgoing packet), if counter exceeds configured limit either do a
311 * hangup immediately or - if configured - wait until just before the next
312 * charge-info.
313 *
314 * cps-calculation (needed for dynamic channel-bundling):
315 * Since this function is called every second, simply reset the
316 * byte-counter of the interface after copying it to the cps-variable.
317 */
Adrian Bunk3e206b02005-06-25 14:58:35 -0700318static unsigned long last_jiffies = -HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320void
321isdn_net_autohup(void)
322{
323 isdn_net_dev *p = dev->netdev;
324 int anymore;
325
326 anymore = 0;
327 while (p) {
328 isdn_net_local *l = p->local;
329 if (jiffies == last_jiffies)
330 l->cps = l->transcount;
331 else
332 l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
333 l->transcount = 0;
334 if (dev->net_verbose > 3)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700335 printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
337 anymore = 1;
338 l->huptimer++;
339 /*
340 * if there is some dialmode where timeout-hangup
341 * should _not_ be done, check for that here
342 */
343 if ((l->onhtime) &&
344 (l->huptimer > l->onhtime))
345 {
346 if (l->hupflags & ISDN_MANCHARGE &&
347 l->hupflags & ISDN_CHARGEHUP) {
348 while (time_after(jiffies, l->chargetime + l->chargeint))
349 l->chargetime += l->chargeint;
350 if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
351 if (l->outgoing || l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700352 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 } else if (l->outgoing) {
354 if (l->hupflags & ISDN_CHARGEHUP) {
355 if (l->hupflags & ISDN_WAITCHARGE) {
356 printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700357 p->dev->name, l->hupflags);
Karsten Keild62a38d2007-10-08 20:37:11 -0700358 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
360 printk(KERN_DEBUG
361 "isdn_net: %s: chtime = %lu, chint = %d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700362 p->dev->name, l->chargetime, l->chargeint);
Karsten Keild62a38d2007-10-08 20:37:11 -0700363 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 }
365 } else
Karsten Keild62a38d2007-10-08 20:37:11 -0700366 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 } else if (l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700368 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 }
370
Joe Perches475be4d2012-02-19 19:52:38 -0800371 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
Karsten Keild62a38d2007-10-08 20:37:11 -0700372 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 break;
374 }
375 }
376 p = (isdn_net_dev *) p->next;
377 }
378 last_jiffies = jiffies;
379 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
380}
381
382static void isdn_net_lp_disconnected(isdn_net_local *lp)
383{
384 isdn_net_rm_from_bundle(lp);
385}
386
387/*
388 * Handle status-messages from ISDN-interfacecard.
389 * This function is called from within the main-status-dispatcher
390 * isdn_status_callback, which itself is called from the low-level driver.
391 * Return: 1 = Event handled, 0 = not for us or unknown Event.
392 */
393int
394isdn_net_stat_callback(int idx, isdn_ctrl *c)
395{
396 isdn_net_dev *p = dev->st_netdev[idx];
397 int cmd = c->command;
398
399 if (p) {
400 isdn_net_local *lp = p->local;
401#ifdef CONFIG_ISDN_X25
402 struct concap_proto *cprot = lp->netdev->cprot;
403 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
404#endif
405 switch (cmd) {
Joe Perches475be4d2012-02-19 19:52:38 -0800406 case ISDN_STAT_BSENT:
407 /* A packet has successfully been sent out */
408 if ((lp->flags & ISDN_NET_CONNECTED) &&
409 (!lp->dialstate)) {
410 isdn_net_dec_frame_cnt(lp);
411 lp->stats.tx_packets++;
412 lp->stats.tx_bytes += c->parm.length;
413 }
414 return 1;
415 case ISDN_STAT_DCONN:
416 /* D-Channel is up */
417 switch (lp->dialstate) {
418 case 4:
419 case 7:
420 case 8:
421 lp->dialstate++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 return 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800423 case 12:
424 lp->dialstate = 5;
425 return 1;
426 }
427 break;
428 case ISDN_STAT_DHUP:
429 /* Either D-Channel-hangup or error during dialout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800431 /* If we are not connencted then dialing had
432 failed. If there are generic encap protocol
433 receiver routines signal the closure of
434 the link*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Joe Perches475be4d2012-02-19 19:52:38 -0800436 if (!(lp->flags & ISDN_NET_CONNECTED)
437 && pops && pops->disconn_ind)
438 pops->disconn_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -0800440 if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
441 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
442 isdn_net_ciscohdlck_disconnected(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800444 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
445 isdn_ppp_free(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446#endif
Joe Perches475be4d2012-02-19 19:52:38 -0800447 isdn_net_lp_disconnected(lp);
448 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
449 printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
450 printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
451 lp->charge);
452 isdn_net_unbind_channel(lp);
453 return 1;
454 }
455 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800457 case ISDN_STAT_BHUP:
458 /* B-Channel-hangup */
459 /* try if there are generic encap protocol
460 receiver routines and signal the closure of
461 the link */
462 if (pops && pops->disconn_ind) {
463 pops->disconn_ind(cprot);
464 return 1;
465 }
466 break;
467#endif /* CONFIG_ISDN_X25 */
468 case ISDN_STAT_BCONN:
469 /* B-Channel is up */
470 isdn_net_zero_frame_cnt(lp);
471 switch (lp->dialstate) {
472 case 5:
473 case 6:
474 case 7:
475 case 8:
476 case 9:
477 case 10:
478 case 12:
479 if (lp->dialstate <= 6) {
480 dev->usage[idx] |= ISDN_USAGE_OUTGOING;
481 isdn_info_update();
482 } else
483 dev->rx_netdev[idx] = p;
484 lp->dialstate = 0;
485 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
486 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
487 isdn_net_ciscohdlck_connected(lp);
488 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
489 if (lp->master) { /* is lp a slave? */
490 isdn_net_dev *nd = ISDN_MASTER_PRIV(lp)->netdev;
491 isdn_net_add_to_bundle(nd, lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
Joe Perches475be4d2012-02-19 19:52:38 -0800493 }
494 printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
495 /* If first Chargeinfo comes before B-Channel connect,
496 * we correct the timestamp here.
497 */
498 lp->chargetime = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Joe Perches475be4d2012-02-19 19:52:38 -0800500 /* reset dial-timeout */
501 lp->dialstarted = 0;
502 lp->dialwait_timer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800505 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
506 isdn_ppp_wakeup_daemon(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507#endif
508#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800509 /* try if there are generic concap receiver routines */
510 if (pops)
511 if (pops->connect_ind)
512 pops->connect_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -0800514 /* ppp needs to do negotiations first */
515 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
516 isdn_net_device_wake_queue(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800518 }
519 break;
520 case ISDN_STAT_NODCH:
521 /* No D-Channel avail. */
522 if (lp->dialstate == 4) {
523 lp->dialstate--;
524 return 1;
525 }
526 break;
527 case ISDN_STAT_CINF:
528 /* Charge-info from TelCo. Calculate interval between
529 * charge-infos and set timestamp for last info for
530 * usage by isdn_net_autohup()
531 */
532 lp->charge++;
533 if (lp->hupflags & ISDN_HAVECHARGE) {
534 lp->hupflags &= ~ISDN_WAITCHARGE;
535 lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
536 }
537 if (lp->hupflags & ISDN_WAITCHARGE)
538 lp->hupflags |= ISDN_HAVECHARGE;
539 lp->chargetime = jiffies;
540 printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
541 p->dev->name, lp->chargetime);
542 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544 }
545 return 0;
546}
547
548/*
549 * Perform dialout for net-interfaces and timeout-handling for
550 * D-Channel-up and B-Channel-up Messages.
551 * This function is initially called from within isdn_net_start_xmit() or
552 * or isdn_net_find_icall() after initializing the dialstate for an
553 * interface. If further calls are needed, the function schedules itself
554 * for a timer-callback via isdn_timer_function().
555 * The dialstate is also affected by incoming status-messages from
556 * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
557 */
558void
559isdn_net_dial(void)
560{
561 isdn_net_dev *p = dev->netdev;
562 int anymore = 0;
563 int i;
564 isdn_ctrl cmd;
Joe Perches475be4d2012-02-19 19:52:38 -0800565 u_char *phone_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
567 while (p) {
568 isdn_net_local *lp = p->local;
569
570#ifdef ISDN_DEBUG_NET_DIAL
571 if (lp->dialstate)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700572 printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#endif
574 switch (lp->dialstate) {
Joe Perches475be4d2012-02-19 19:52:38 -0800575 case 0:
576 /* Nothing to do for this interface */
577 break;
578 case 1:
579 /* Initiate dialout. Set phone-number-pointer to first number
580 * of interface.
581 */
582 lp->dial = lp->phone[1];
583 if (!lp->dial) {
584 printk(KERN_WARNING "%s: phone number deleted?\n",
585 p->dev->name);
586 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800588 }
589 anymore = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Joe Perches475be4d2012-02-19 19:52:38 -0800591 if (lp->dialtimeout > 0)
592 if (lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
593 lp->dialstarted = jiffies;
594 lp->dialwait_timer = 0;
595 }
596
597 lp->dialstate++;
598 /* Fall through */
599 case 2:
600 /* Prepare dialing. Clear EAZ, then set EAZ. */
601 cmd.driver = lp->isdn_device;
602 cmd.arg = lp->isdn_channel;
603 cmd.command = ISDN_CMD_CLREAZ;
604 isdn_command(&cmd);
605 sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
606 cmd.command = ISDN_CMD_SETEAZ;
607 isdn_command(&cmd);
608 lp->dialretry = 0;
609 anymore = 1;
610 lp->dialstate++;
611 /* Fall through */
612 case 3:
613 /* Setup interface, dial current phone-number, switch to next number.
614 * If list of phone-numbers is exhausted, increment
615 * retry-counter.
616 */
617 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
618 char *s;
619 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
620 s = "dial suppressed: isdn system stopped";
621 else
622 s = "dial suppressed: dialmode `off'";
623 isdn_net_unreachable(p->dev, NULL, s);
624 isdn_net_hangup(p->dev);
625 break;
626 }
627 cmd.driver = lp->isdn_device;
628 cmd.command = ISDN_CMD_SETL2;
629 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
630 isdn_command(&cmd);
631 cmd.driver = lp->isdn_device;
632 cmd.command = ISDN_CMD_SETL3;
633 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
634 isdn_command(&cmd);
635 cmd.driver = lp->isdn_device;
636 cmd.arg = lp->isdn_channel;
637 if (!lp->dial) {
638 printk(KERN_WARNING "%s: phone number deleted?\n",
639 p->dev->name);
640 isdn_net_hangup(p->dev);
641 break;
642 }
643 if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
644 lp->dialstate = 4;
645 printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
646 } else {
647 if (lp->dialtimeout > 0)
648 if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
649 lp->dialwait_timer = jiffies + lp->dialwait;
650 lp->dialstarted = 0;
651 isdn_net_unreachable(p->dev, NULL, "dial: timed out");
652 isdn_net_hangup(p->dev);
653 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 cmd.driver = lp->isdn_device;
Joe Perches475be4d2012-02-19 19:52:38 -0800657 cmd.command = ISDN_CMD_DIAL;
658 cmd.parm.setup.si2 = 0;
659
660 /* check for DOV */
661 phone_number = lp->dial->num;
662 if ((*phone_number == 'v') ||
663 (*phone_number == 'V')) { /* DOV call */
664 cmd.parm.setup.si1 = 1;
665 } else { /* DATA call */
666 cmd.parm.setup.si1 = 7;
667 }
668
669 strcpy(cmd.parm.setup.phone, phone_number);
670 /*
671 * Switch to next number or back to start if at end of list.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 */
Joe Perches475be4d2012-02-19 19:52:38 -0800673 if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
674 lp->dial = lp->phone[1];
675 lp->dialretry++;
676
677 if (lp->dialretry > lp->dialmax) {
678 if (lp->dialtimeout == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 lp->dialwait_timer = jiffies + lp->dialwait;
680 lp->dialstarted = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800681 isdn_net_unreachable(p->dev, NULL, "dial: tried all numbers dialmax times");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 }
Joe Perches475be4d2012-02-19 19:52:38 -0800683 isdn_net_hangup(p->dev);
684 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
Joe Perches475be4d2012-02-19 19:52:38 -0800687 sprintf(cmd.parm.setup.eazmsn, "%s",
688 isdn_map_eaz2msn(lp->msn, cmd.driver));
689 i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
690 if (i >= 0) {
691 strcpy(dev->num[i], cmd.parm.setup.phone);
692 dev->usage[i] |= ISDN_USAGE_OUTGOING;
693 isdn_info_update();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
Joe Perches475be4d2012-02-19 19:52:38 -0800695 printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
696 lp->dialretry, cmd.parm.setup.phone,
697 (cmd.parm.setup.si1 == 1) ? "DOV" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 lp->dtimer = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800699#ifdef ISDN_DEBUG_NET_DIAL
700 printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
701 lp->isdn_channel);
702#endif
703 isdn_command(&cmd);
704 }
705 lp->huptimer = 0;
706 lp->outgoing = 1;
707 if (lp->chargeint) {
708 lp->hupflags |= ISDN_HAVECHARGE;
709 lp->hupflags &= ~ISDN_WAITCHARGE;
710 } else {
711 lp->hupflags |= ISDN_WAITCHARGE;
712 lp->hupflags &= ~ISDN_HAVECHARGE;
713 }
714 anymore = 1;
715 lp->dialstate =
716 (lp->cbdelay &&
717 (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
718 break;
719 case 4:
720 /* Wait for D-Channel-connect.
721 * If timeout, switch back to state 3.
722 * Dialmax-handling moved to state 3.
723 */
724 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
725 lp->dialstate = 3;
726 anymore = 1;
727 break;
728 case 5:
729 /* Got D-Channel-Connect, send B-Channel-request */
730 cmd.driver = lp->isdn_device;
731 cmd.arg = lp->isdn_channel;
732 cmd.command = ISDN_CMD_ACCEPTB;
733 anymore = 1;
734 lp->dtimer = 0;
735 lp->dialstate++;
736 isdn_command(&cmd);
737 break;
738 case 6:
739 /* Wait for B- or D-Channel-connect. If timeout,
740 * switch back to state 3.
741 */
742#ifdef ISDN_DEBUG_NET_DIAL
743 printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
744#endif
745 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
746 lp->dialstate = 3;
747 anymore = 1;
748 break;
749 case 7:
750 /* Got incoming Call, setup L2 and L3 protocols,
751 * then wait for D-Channel-connect
752 */
753#ifdef ISDN_DEBUG_NET_DIAL
754 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
755#endif
756 cmd.driver = lp->isdn_device;
757 cmd.command = ISDN_CMD_SETL2;
758 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
759 isdn_command(&cmd);
760 cmd.driver = lp->isdn_device;
761 cmd.command = ISDN_CMD_SETL3;
762 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
763 isdn_command(&cmd);
764 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
765 isdn_net_hangup(p->dev);
766 else {
767 anymore = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 lp->dialstate++;
Joe Perches475be4d2012-02-19 19:52:38 -0800769 }
770 break;
771 case 9:
772 /* Got incoming D-Channel-Connect, send B-Channel-request */
773 cmd.driver = lp->isdn_device;
774 cmd.arg = lp->isdn_channel;
775 cmd.command = ISDN_CMD_ACCEPTB;
776 isdn_command(&cmd);
777 anymore = 1;
778 lp->dtimer = 0;
779 lp->dialstate++;
780 break;
781 case 8:
782 case 10:
783 /* Wait for B- or D-channel-connect */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784#ifdef ISDN_DEBUG_NET_DIAL
Joe Perches475be4d2012-02-19 19:52:38 -0800785 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786#endif
Joe Perches475be4d2012-02-19 19:52:38 -0800787 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
788 isdn_net_hangup(p->dev);
789 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 anymore = 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800791 break;
792 case 11:
793 /* Callback Delay */
794 if (lp->dtimer++ > lp->cbdelay)
795 lp->dialstate = 1;
796 anymore = 1;
797 break;
798 case 12:
799 /* Remote does callback. Hangup after cbdelay, then wait for incoming
800 * call (in state 4).
801 */
802 if (lp->dtimer++ > lp->cbdelay)
803 {
804 printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 lp->dtimer = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800806 lp->dialstate = 4;
807 cmd.driver = lp->isdn_device;
808 cmd.command = ISDN_CMD_HANGUP;
809 cmd.arg = lp->isdn_channel;
810 isdn_command(&cmd);
811 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
812 }
813 anymore = 1;
814 break;
815 default:
816 printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
817 lp->dialstate, p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 }
819 p = (isdn_net_dev *) p->next;
820 }
821 isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
822}
823
824/*
825 * Perform hangup for a net-interface.
826 */
827void
828isdn_net_hangup(struct net_device *d)
829{
Joe Perchesa17531f2010-11-15 11:12:24 +0000830 isdn_net_local *lp = netdev_priv(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 isdn_ctrl cmd;
832#ifdef CONFIG_ISDN_X25
833 struct concap_proto *cprot = lp->netdev->cprot;
834 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
835#endif
836
837 if (lp->flags & ISDN_NET_CONNECTED) {
838 if (lp->slave != NULL) {
Wang Chen838361f2008-12-03 15:49:46 -0800839 isdn_net_local *slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (slp->flags & ISDN_NET_CONNECTED) {
841 printk(KERN_INFO
Joe Perches475be4d2012-02-19 19:52:38 -0800842 "isdn_net: hang up slave %s before %s\n",
843 lp->slave->name, d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 isdn_net_hangup(lp->slave);
845 }
846 }
Karsten Keilfaca94f2007-10-15 02:11:44 -0700847 printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848#ifdef CONFIG_ISDN_PPP
849 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
850 isdn_ppp_free(lp);
851#endif
852 isdn_net_lp_disconnected(lp);
853#ifdef CONFIG_ISDN_X25
854 /* try if there are generic encap protocol
855 receiver routines and signal the closure of
856 the link */
Joe Perches475be4d2012-02-19 19:52:38 -0800857 if (pops && pops->disconn_ind)
858 pops->disconn_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859#endif /* CONFIG_ISDN_X25 */
860
861 cmd.driver = lp->isdn_device;
862 cmd.command = ISDN_CMD_HANGUP;
863 cmd.arg = lp->isdn_channel;
864 isdn_command(&cmd);
Karsten Keilfaca94f2007-10-15 02:11:44 -0700865 printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
867 }
868 isdn_net_unbind_channel(lp);
869}
870
871typedef struct {
Harvey Harrisonc19d0362008-11-20 04:10:51 -0800872 __be16 source;
873 __be16 dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874} ip_ports;
875
876static void
Joe Perches475be4d2012-02-19 19:52:38 -0800877isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878{
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -0700879 /* hopefully, this was set correctly */
880 const u_char *p = skb_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 unsigned short proto = ntohs(skb->protocol);
882 int data_ofs;
883 ip_ports *ipp;
884 char addinfo[100];
885
886 addinfo[0] = '\0';
887 /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
Simon Horman25b6e142013-05-28 20:34:23 +0000888 if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* fall back to old isdn_net_log_packet method() */
Joe Perches475be4d2012-02-19 19:52:38 -0800890 char *buf = skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Karsten Keilfaca94f2007-10-15 02:11:44 -0700892 printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 p = buf;
894 proto = ETH_P_IP;
895 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -0800896 case ISDN_NET_ENCAP_IPTYP:
897 proto = ntohs(*(__be16 *)&buf[0]);
898 p = &buf[2];
899 break;
900 case ISDN_NET_ENCAP_ETHER:
901 proto = ntohs(*(__be16 *)&buf[12]);
902 p = &buf[14];
903 break;
904 case ISDN_NET_ENCAP_CISCOHDLC:
905 proto = ntohs(*(__be16 *)&buf[2]);
906 p = &buf[4];
907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800909 case ISDN_NET_ENCAP_SYNCPPP:
910 proto = ntohs(skb->protocol);
911 p = &buf[IPPP_MAX_HEADER];
912 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913#endif
914 }
915 }
916 data_ofs = ((p[0] & 15) * 4);
917 switch (proto) {
Joe Perches475be4d2012-02-19 19:52:38 -0800918 case ETH_P_IP:
919 switch (p[9]) {
920 case 1:
921 strcpy(addinfo, " ICMP");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800923 case 2:
924 strcpy(addinfo, " IGMP");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800926 case 4:
927 strcpy(addinfo, " IPIP");
928 break;
929 case 6:
930 ipp = (ip_ports *) (&p[data_ofs]);
931 sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
932 ntohs(ipp->dest));
933 break;
934 case 8:
935 strcpy(addinfo, " EGP");
936 break;
937 case 12:
938 strcpy(addinfo, " PUP");
939 break;
940 case 17:
941 ipp = (ip_ports *) (&p[data_ofs]);
942 sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
943 ntohs(ipp->dest));
944 break;
945 case 22:
946 strcpy(addinfo, " IDP");
947 break;
948 }
949 printk(KERN_INFO "OPEN: %pI4 -> %pI4%s\n",
950 p + 12, p + 16, addinfo);
951 break;
952 case ETH_P_ARP:
953 printk(KERN_INFO "OPEN: ARP %pI4 -> *.*.*.* ?%pI4\n",
954 p + 14, p + 24);
955 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 }
957}
958
959/*
960 * this function is used to send supervisory data, i.e. data which was
961 * not received from the network layer, but e.g. frames from ipppd, CCP
962 * reset frames etc.
963 */
964void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
965{
966 if (in_irq()) {
Joe Perches475be4d2012-02-19 19:52:38 -0800967 // we can't grab the lock from irq context,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 // so we just queue the packet
969 skb_queue_tail(&lp->super_tx_queue, skb);
970 schedule_work(&lp->tqueue);
971 return;
972 }
973
974 spin_lock_bh(&lp->xmit_lock);
975 if (!isdn_net_lp_busy(lp)) {
976 isdn_net_writebuf_skb(lp, skb);
977 } else {
978 skb_queue_tail(&lp->super_tx_queue, skb);
979 }
980 spin_unlock_bh(&lp->xmit_lock);
981}
982
983/*
984 * called from tq_immediate
985 */
David Howellsc4028952006-11-22 14:57:56 +0000986static void isdn_net_softint(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
David Howellsc4028952006-11-22 14:57:56 +0000988 isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 struct sk_buff *skb;
990
991 spin_lock_bh(&lp->xmit_lock);
992 while (!isdn_net_lp_busy(lp)) {
993 skb = skb_dequeue(&lp->super_tx_queue);
994 if (!skb)
995 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800996 isdn_net_writebuf_skb(lp, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
998 spin_unlock_bh(&lp->xmit_lock);
999}
1000
Joe Perches475be4d2012-02-19 19:52:38 -08001001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 * all frames sent from the (net) LL to a HL driver should go via this function
1003 * it's serialized by the caller holding the lp->xmit_lock spinlock
1004 */
1005void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
1006{
1007 int ret;
1008 int len = skb->len; /* save len */
1009
1010 /* before obtaining the lock the caller should have checked that
1011 the lp isn't busy */
1012 if (isdn_net_lp_busy(lp)) {
1013 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1014 goto error;
1015 }
1016
1017 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1018 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1019 goto error;
1020 }
1021 ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
1022 if (ret != len) {
1023 /* we should never get here */
Karsten Keilfaca94f2007-10-15 02:11:44 -07001024 printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 goto error;
1026 }
Joe Perches475be4d2012-02-19 19:52:38 -08001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 lp->transcount += len;
1029 isdn_net_inc_frame_cnt(lp);
1030 return;
1031
Joe Perches475be4d2012-02-19 19:52:38 -08001032error:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 dev_kfree_skb(skb);
1034 lp->stats.tx_errors++;
1035
1036}
1037
1038
1039/*
1040 * Helper function for isdn_net_start_xmit.
1041 * When called, the connection is already established.
1042 * Based on cps-calculation, check if device is overloaded.
1043 * If so, and if a slave exists, trigger dialing for it.
1044 * If any slave is online, deliver packets using a simple round robin
1045 * scheme.
1046 *
1047 * Return: 0 on success, !0 on failure.
1048 */
1049
1050static int
1051isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
1052{
1053 isdn_net_dev *nd;
1054 isdn_net_local *slp;
Joe Perchesa17531f2010-11-15 11:12:24 +00001055 isdn_net_local *lp = netdev_priv(ndev);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001056 int retv = NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Wang Chen838361f2008-12-03 15:49:46 -08001058 if (((isdn_net_local *) netdev_priv(ndev))->master) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1060 dev_kfree_skb(skb);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001061 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
1064 /* For the other encaps the header has already been built */
1065#ifdef CONFIG_ISDN_PPP
1066 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1067 return isdn_ppp_xmit(skb, ndev);
1068 }
1069#endif
Wang Chen838361f2008-12-03 15:49:46 -08001070 nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 lp = isdn_net_get_locked_lp(nd);
1072 if (!lp) {
1073 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
Patrick McHardy5b548142009-06-12 06:22:29 +00001074 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 }
1076 /* we have our lp locked from now on */
1077
1078 /* Reset hangup-timeout */
1079 lp->huptimer = 0; // FIXME?
1080 isdn_net_writebuf_skb(lp, skb);
1081 spin_unlock_bh(&lp->xmit_lock);
1082
1083 /* the following stuff is here for backwards compatibility.
1084 * in future, start-up and hangup of slaves (based on current load)
1085 * should move to userspace and get based on an overall cps
1086 * calculation
1087 */
1088 if (lp->cps > lp->triggercps) {
1089 if (lp->slave) {
1090 if (!lp->sqfull) {
1091 /* First time overload: set timestamp only */
1092 lp->sqfull = 1;
1093 lp->sqfull_stamp = jiffies;
1094 } else {
1095 /* subsequent overload: if slavedelay exceeded, start dialing */
1096 if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
Wang Chen838361f2008-12-03 15:49:46 -08001097 slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (!(slp->flags & ISDN_NET_CONNECTED)) {
Wang Chen838361f2008-12-03 15:49:46 -08001099 isdn_net_force_dial_lp(ISDN_SLAVE_PRIV(lp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 }
1102 }
1103 }
1104 } else {
1105 if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
1106 lp->sqfull = 0;
1107 }
1108 /* this is a hack to allow auto-hangup for slaves on moderate loads */
1109 nd->queue = nd->local;
1110 }
1111
1112 return retv;
1113
1114}
1115
1116static void
1117isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
1118{
Joe Perchesa17531f2010-11-15 11:12:24 +00001119 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (!skb)
1121 return;
1122 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001123 const int pullsize = skb_network_offset(skb) - ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 if (pullsize > 0) {
1125 printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
1126 skb_pull(skb, pullsize);
1127 }
1128 }
1129}
1130
1131
Joe Perches475be4d2012-02-19 19:52:38 -08001132static void isdn_net_tx_timeout(struct net_device *ndev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Joe Perchesa17531f2010-11-15 11:12:24 +00001134 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
Joe Perches475be4d2012-02-19 19:52:38 -08001137 if (!lp->dialstate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 lp->stats.tx_errors++;
Joe Perches475be4d2012-02-19 19:52:38 -08001139 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 * There is a certain probability that this currently
1141 * works at all because if we always wake up the interface,
1142 * then upper layer will try to send the next packet
1143 * immediately. And then, the old clean_up logic in the
1144 * driver will hopefully continue to work as it used to do.
1145 *
1146 * This is rather primitive right know, we better should
1147 * clean internal queues here, in particular for multilink and
1148 * ppp, and reset HL driver's channel, too. --HE
1149 *
1150 * actually, this may not matter at all, because ISDN hardware
1151 * should not see transmitter hangs at all IMO
Joe Perches475be4d2012-02-19 19:52:38 -08001152 * changed KERN_DEBUG to KERN_WARNING to find out if this is
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 * ever called --KG
1154 */
1155 }
1156 ndev->trans_start = jiffies;
1157 netif_wake_queue(ndev);
1158}
1159
1160/*
1161 * Try sending a packet.
1162 * If this interface isn't connected to a ISDN-Channel, find a free channel,
1163 * and start dialing.
1164 */
Stephen Hemminger8b62ff22009-08-31 19:50:44 +00001165static netdev_tx_t
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1167{
Joe Perchesa17531f2010-11-15 11:12:24 +00001168 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001170 struct concap_proto *cprot = lp->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171/* At this point hard_start_xmit() passes control to the encapsulation
1172 protocol (if present).
1173 For X.25 auto-dialing is completly bypassed because:
1174 - It does not conform with the semantics of a reliable datalink
Joe Perches475be4d2012-02-19 19:52:38 -08001175 service as needed by X.25 PLP.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 - I don't want that the interface starts dialing when the network layer
Joe Perches475be4d2012-02-19 19:52:38 -08001177 sends a message which requests to disconnect the lapb link (or if it
1178 sends any other message not resulting in data transmission).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 Instead, dialing will be initiated by the encapsulation protocol entity
1180 when a dl_establish request is received from the upper layer.
1181*/
Joe Perches475be4d2012-02-19 19:52:38 -08001182 if (cprot && cprot->pops) {
1183 int ret = cprot->pops->encap_and_xmit(cprot, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 if (ret)
1186 netif_stop_queue(ndev);
1187 return ret;
1188 } else
1189#endif
Joe Perches475be4d2012-02-19 19:52:38 -08001190 /* auto-dialing xmit function */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 {
1192#ifdef ISDN_DEBUG_NET_DUMP
1193 u_char *buf;
1194#endif
1195 isdn_net_adjust_hdr(skb, ndev);
1196#ifdef ISDN_DEBUG_NET_DUMP
1197 buf = skb->data;
1198 isdn_dumppkt("S:", buf, skb->len, 40);
1199#endif
1200
1201 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1202 int chi;
1203 /* only do autodial if allowed by config */
1204 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
1205 isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
1206 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001207 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209 if (lp->phone[1]) {
1210 ulong flags;
1211
Joe Perches475be4d2012-02-19 19:52:38 -08001212 if (lp->dialwait_timer <= 0)
1213 if (lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
1215
Joe Perches475be4d2012-02-19 19:52:38 -08001216 if (lp->dialwait_timer > 0) {
1217 if (time_before(jiffies, lp->dialwait_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
1219 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001220 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 } else
1222 lp->dialwait_timer = 0;
1223 }
1224 /* Grab a free ISDN-Channel */
1225 spin_lock_irqsave(&dev->lock, flags);
1226 if (((chi =
Joe Perches475be4d2012-02-19 19:52:38 -08001227 isdn_get_free_channel(
1228 ISDN_USAGE_NET,
1229 lp->l2_proto,
1230 lp->l3_proto,
1231 lp->pre_device,
1232 lp->pre_channel,
1233 lp->msn)
1234 ) < 0) &&
1235 ((chi =
1236 isdn_get_free_channel(
1237 ISDN_USAGE_NET,
1238 lp->l2_proto,
1239 lp->l3_proto,
1240 lp->pre_device,
1241 lp->pre_channel^1,
1242 lp->msn)
1243 ) < 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 spin_unlock_irqrestore(&dev->lock, flags);
1245 isdn_net_unreachable(ndev, skb,
Joe Perches475be4d2012-02-19 19:52:38 -08001246 "No channel");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001248 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 }
1250 /* Log packet, which triggered dialing */
1251 if (dev->net_verbose)
1252 isdn_net_log_skb(skb, lp);
1253 lp->dialstate = 1;
1254 /* Connect interface with channel */
1255 isdn_net_bind_channel(lp, chi);
1256#ifdef CONFIG_ISDN_PPP
1257 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1258 /* no 'first_skb' handling for syncPPP */
1259 if (isdn_ppp_bind(lp) < 0) {
1260 dev_kfree_skb(skb);
1261 isdn_net_unbind_channel(lp);
1262 spin_unlock_irqrestore(&dev->lock, flags);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001263 return NETDEV_TX_OK; /* STN (skb to nirvana) ;) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 }
1265#ifdef CONFIG_IPPP_FILTER
1266 if (isdn_ppp_autodial_filter(skb, lp)) {
1267 isdn_ppp_free(lp);
1268 isdn_net_unbind_channel(lp);
1269 spin_unlock_irqrestore(&dev->lock, flags);
1270 isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
1271 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001272 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 }
1274#endif
1275 spin_unlock_irqrestore(&dev->lock, flags);
1276 isdn_net_dial(); /* Initiate dialing */
1277 netif_stop_queue(ndev);
Patrick McHardy5b548142009-06-12 06:22:29 +00001278 return NETDEV_TX_BUSY; /* let upper layer requeue skb packet */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 }
1280#endif
1281 /* Initiate dialing */
1282 spin_unlock_irqrestore(&dev->lock, flags);
1283 isdn_net_dial();
1284 isdn_net_device_stop_queue(lp);
Patrick McHardy5b548142009-06-12 06:22:29 +00001285 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 } else {
1287 isdn_net_unreachable(ndev, skb,
1288 "No phone number");
1289 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001290 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
1292 } else {
Joe Perches475be4d2012-02-19 19:52:38 -08001293 /* Device is connected to an ISDN channel */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 ndev->trans_start = jiffies;
1295 if (!lp->dialstate) {
1296 /* ISDN connection is established, try sending */
1297 int ret;
1298 ret = (isdn_net_xmit(ndev, skb));
Joe Perches475be4d2012-02-19 19:52:38 -08001299 if (ret) netif_stop_queue(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 return ret;
1301 } else
1302 netif_stop_queue(ndev);
1303 }
1304 }
Patrick McHardyd77eeb72009-06-15 23:33:24 +00001305 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306}
1307
1308/*
1309 * Shutdown a net-interface.
1310 */
1311static int
1312isdn_net_close(struct net_device *dev)
1313{
1314 struct net_device *p;
1315#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001316 struct concap_proto *cprot =
1317 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
1318 /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319#endif
1320
1321#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001322 if (cprot && cprot->pops) cprot->pops->close(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323#endif
1324 netif_stop_queue(dev);
Wang Chen838361f2008-12-03 15:49:46 -08001325 p = MASTER_TO_SLAVE(dev);
1326 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 /* If this interface has slaves, stop them also */
1328 while (p) {
1329#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001330 cprot = ((isdn_net_local *)netdev_priv(p))
1331 ->netdev->cprot;
1332 if (cprot && cprot->pops)
1333 cprot->pops->close(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334#endif
1335 isdn_net_hangup(p);
Wang Chen838361f2008-12-03 15:49:46 -08001336 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
1338 }
1339 isdn_net_hangup(dev);
1340 isdn_unlock_drivers();
1341 return 0;
1342}
1343
1344/*
1345 * Get statistics
1346 */
1347static struct net_device_stats *
1348isdn_net_get_stats(struct net_device *dev)
1349{
Joe Perchesa17531f2010-11-15 11:12:24 +00001350 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return &lp->stats;
1352}
1353
1354/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
1355 * instead of dev->hard_header_len off. This is done because the
1356 * lowlevel-driver has already pulled off its stuff when we get
1357 * here and this routine only gets called with p_encap == ETHER.
1358 * Determine the packet's protocol ID. The rule here is that we
1359 * assume 802.3 if the type field is short enough to be a length.
1360 * This is normal practice and works for any 'now in use' protocol.
1361 */
1362
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001363static __be16
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
1365{
1366 struct ethhdr *eth;
1367 unsigned char *rawp;
1368
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -07001369 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 skb_pull(skb, ETH_HLEN);
1371 eth = eth_hdr(skb);
1372
1373 if (*eth->h_dest & 1) {
1374 if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
1375 skb->pkt_type = PACKET_BROADCAST;
1376 else
1377 skb->pkt_type = PACKET_MULTICAST;
1378 }
1379 /*
1380 * This ALLMULTI check should be redundant by 1.4
1381 * so don't forget to remove it.
1382 */
1383
1384 else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
1385 if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
1386 skb->pkt_type = PACKET_OTHERHOST;
1387 }
Simon Hormane5c5d222013-03-28 13:38:25 +09001388 if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return eth->h_proto;
1390
1391 rawp = skb->data;
1392
1393 /*
1394 * This is a magic hack to spot IPX packets. Older Novell breaks
1395 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
1396 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
1397 * won't work for fault tolerant netware but does for the rest.
1398 */
1399 if (*(unsigned short *) rawp == 0xFFFF)
1400 return htons(ETH_P_802_3);
1401 /*
1402 * Real 802.2 LLC
1403 */
1404 return htons(ETH_P_802_2);
1405}
1406
1407
Joe Perches475be4d2012-02-19 19:52:38 -08001408/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 * CISCO HDLC keepalive specific stuff
1410 */
1411static struct sk_buff*
1412isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
1413{
1414 unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
1415 struct sk_buff *skb;
1416
1417 skb = alloc_skb(hl + len, GFP_ATOMIC);
1418 if (skb)
1419 skb_reserve(skb, hl);
Joe Perches475be4d2012-02-19 19:52:38 -08001420 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
1422 return skb;
1423}
1424
1425/* cisco hdlck device private ioctls */
Adrian Bunk3e206b02005-06-25 14:58:35 -07001426static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1428{
Joe Perchesa17531f2010-11-15 11:12:24 +00001429 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 unsigned long len = 0;
1431 unsigned long expires = 0;
1432 int tmp = 0;
1433 int period = lp->cisco_keepalive_period;
1434 s8 debserint = lp->cisco_debserint;
1435 int rc = 0;
1436
1437 if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
1438 return -EINVAL;
1439
1440 switch (cmd) {
1441 /* get/set keepalive period */
Joe Perches475be4d2012-02-19 19:52:38 -08001442 case SIOCGKEEPPERIOD:
1443 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1444 if (copy_to_user(ifr->ifr_data,
1445 &lp->cisco_keepalive_period, len))
1446 rc = -EFAULT;
1447 break;
1448 case SIOCSKEEPPERIOD:
1449 tmp = lp->cisco_keepalive_period;
1450 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1451 if (copy_from_user(&period, ifr->ifr_data, len))
1452 rc = -EFAULT;
1453 if ((period > 0) && (period <= 32767))
1454 lp->cisco_keepalive_period = period;
1455 else
1456 rc = -EINVAL;
1457 if (!rc && (tmp != lp->cisco_keepalive_period)) {
1458 expires = (unsigned long)(jiffies +
1459 lp->cisco_keepalive_period * HZ);
1460 mod_timer(&lp->cisco_timer, expires);
1461 printk(KERN_INFO "%s: Keepalive period set "
1462 "to %d seconds.\n",
1463 dev->name, lp->cisco_keepalive_period);
1464 }
1465 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 /* get/set debugging */
Joe Perches475be4d2012-02-19 19:52:38 -08001468 case SIOCGDEBSERINT:
1469 len = (unsigned long)sizeof(lp->cisco_debserint);
1470 if (copy_to_user(ifr->ifr_data,
1471 &lp->cisco_debserint, len))
1472 rc = -EFAULT;
1473 break;
1474 case SIOCSDEBSERINT:
1475 len = (unsigned long)sizeof(lp->cisco_debserint);
1476 if (copy_from_user(&debserint,
1477 ifr->ifr_data, len))
1478 rc = -EFAULT;
1479 if ((debserint >= 0) && (debserint <= 64))
1480 lp->cisco_debserint = debserint;
1481 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 rc = -EINVAL;
Joe Perches475be4d2012-02-19 19:52:38 -08001483 break;
1484
1485 default:
1486 rc = -EINVAL;
1487 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 }
1489 return (rc);
1490}
1491
Stephen Hemmingerd7005552009-01-07 18:04:17 -08001492
1493static int isdn_net_ioctl(struct net_device *dev,
1494 struct ifreq *ifr, int cmd)
1495{
Joe Perchesa17531f2010-11-15 11:12:24 +00001496 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemmingerd7005552009-01-07 18:04:17 -08001497
1498 switch (lp->p_encap) {
1499#ifdef CONFIG_ISDN_PPP
1500 case ISDN_NET_ENCAP_SYNCPPP:
1501 return isdn_ppp_dev_ioctl(dev, ifr, cmd);
1502#endif
1503 case ISDN_NET_ENCAP_CISCOHDLCK:
1504 return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
1505 default:
1506 return -EINVAL;
1507 }
1508}
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510/* called via cisco_timer.function */
1511static void
1512isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
1513{
1514 isdn_net_local *lp = (isdn_net_local *) data;
1515 struct sk_buff *skb;
1516 unsigned char *p;
1517 unsigned long last_cisco_myseq = lp->cisco_myseq;
1518 int myseq_diff = 0;
1519
1520 if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
1521 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1522 return;
1523 }
1524 lp->cisco_myseq++;
1525
1526 myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
Joe Perches475be4d2012-02-19 19:52:38 -08001527 if ((lp->cisco_line_state) && ((myseq_diff >= 3) || (myseq_diff <= -3))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 /* line up -> down */
1529 lp->cisco_line_state = 0;
Joe Perches475be4d2012-02-19 19:52:38 -08001530 printk(KERN_WARNING
1531 "UPDOWN: Line protocol on Interface %s,"
1532 " changed state to down\n", lp->netdev->dev->name);
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001533 /* should stop routing higher-level data across */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 } else if ((!lp->cisco_line_state) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001535 (myseq_diff >= 0) && (myseq_diff <= 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 /* line down -> up */
1537 lp->cisco_line_state = 1;
Joe Perches475be4d2012-02-19 19:52:38 -08001538 printk(KERN_WARNING
1539 "UPDOWN: Line protocol on Interface %s,"
1540 " changed state to up\n", lp->netdev->dev->name);
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001541 /* restart routing higher-level data across */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 }
1543
1544 if (lp->cisco_debserint)
Joe Perches475be4d2012-02-19 19:52:38 -08001545 printk(KERN_DEBUG "%s: HDLC "
1546 "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
1547 lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
1548 ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
1549 lp->cisco_yourseq,
1550 ((lp->cisco_line_state) ? "line up" : "line down"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1553 if (!skb)
1554 return;
1555
1556 p = skb_put(skb, 4 + 14);
1557
1558 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001559 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1560 *(u8 *)(p + 1) = CISCO_CTRL;
1561 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
1563 /* slarp keepalive */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001564 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE);
1565 *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq);
1566 *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq);
Dirk Hohndel06fe9fb2009-09-28 21:43:57 -04001567 *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff
Harvey Harrison00bcd522008-11-13 22:41:29 -08001568 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 isdn_net_write_super(lp, skb);
1571
1572 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
Joe Perches475be4d2012-02-19 19:52:38 -08001573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 add_timer(&lp->cisco_timer);
1575}
1576
1577static void
1578isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
1579{
1580 struct sk_buff *skb;
1581 unsigned char *p;
1582
1583 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1584 if (!skb)
1585 return;
1586
1587 p = skb_put(skb, 4 + 14);
1588
1589 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001590 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1591 *(u8 *)(p + 1) = CISCO_CTRL;
1592 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593
1594 /* slarp request */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001595 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REQUEST);
1596 *(__be32 *)(p + 8) = cpu_to_be32(0); // address
1597 *(__be32 *)(p + 12) = cpu_to_be32(0); // netmask
1598 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1599 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
1601 isdn_net_write_super(lp, skb);
1602}
1603
Joe Perches475be4d2012-02-19 19:52:38 -08001604static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605isdn_net_ciscohdlck_connected(isdn_net_local *lp)
1606{
1607 lp->cisco_myseq = 0;
1608 lp->cisco_mineseen = 0;
1609 lp->cisco_yourseq = 0;
1610 lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
1611 lp->cisco_last_slarp_in = 0;
1612 lp->cisco_line_state = 0;
1613 lp->cisco_debserint = 0;
1614
1615 /* send slarp request because interface/seq.no.s reset */
1616 isdn_net_ciscohdlck_slarp_send_request(lp);
1617
1618 init_timer(&lp->cisco_timer);
1619 lp->cisco_timer.data = (unsigned long) lp;
1620 lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
1621 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1622 add_timer(&lp->cisco_timer);
1623}
1624
Joe Perches475be4d2012-02-19 19:52:38 -08001625static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
1627{
1628 del_timer(&lp->cisco_timer);
1629}
1630
1631static void
1632isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
1633{
1634 struct sk_buff *skb;
1635 unsigned char *p;
1636 struct in_device *in_dev = NULL;
Al Viroa144ea42006-09-28 18:00:55 -07001637 __be32 addr = 0; /* local ipv4 address */
1638 __be32 mask = 0; /* local netmask */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Karsten Keild62a38d2007-10-08 20:37:11 -07001640 if ((in_dev = lp->netdev->dev->ip_ptr) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 /* take primary(first) address of interface */
1642 struct in_ifaddr *ifa = in_dev->ifa_list;
1643 if (ifa != NULL) {
1644 addr = ifa->ifa_local;
1645 mask = ifa->ifa_mask;
1646 }
1647 }
1648
1649 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1650 if (!skb)
1651 return;
1652
1653 p = skb_put(skb, 4 + 14);
1654
1655 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001656 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1657 *(u8 *)(p + 1) = CISCO_CTRL;
1658 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
1660 /* slarp reply, send own ip/netmask; if values are nonsense remote
1661 * should think we are unable to provide it with an address via SLARP */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001662 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REPLY);
David S. Miller198d6ba2008-11-18 23:38:23 -08001663 *(__be32 *)(p + 8) = addr; // address
1664 *(__be32 *)(p + 12) = mask; // netmask
Harvey Harrison00bcd522008-11-13 22:41:29 -08001665 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1666 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
1668 isdn_net_write_super(lp, skb);
1669}
1670
1671static void
1672isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
1673{
1674 unsigned char *p;
1675 int period;
1676 u32 code;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001677 u32 my_seq;
1678 u32 your_seq;
1679 __be32 local;
1680 __be32 *addr, *mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
1682 if (skb->len < 14)
1683 return;
1684
1685 p = skb->data;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001686 code = be32_to_cpup((__be32 *)p);
1687 p += 4;
1688
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 switch (code) {
1690 case CISCO_SLARP_REQUEST:
1691 lp->cisco_yourseq = 0;
1692 isdn_net_ciscohdlck_slarp_send_reply(lp);
1693 break;
1694 case CISCO_SLARP_REPLY:
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001695 addr = (__be32 *)p;
1696 mask = (__be32 *)(p + 4);
1697 if (*mask != cpu_to_be32(0xfffffffc))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698 goto slarp_reply_out;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001699 if ((*addr & cpu_to_be32(3)) == cpu_to_be32(0) ||
1700 (*addr & cpu_to_be32(3)) == cpu_to_be32(3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 goto slarp_reply_out;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001702 local = *addr ^ cpu_to_be32(3);
1703 printk(KERN_INFO "%s: got slarp reply: remote ip: %pI4, local ip: %pI4 mask: %pI4\n",
1704 lp->netdev->dev->name, addr, &local, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 break;
Joe Perches475be4d2012-02-19 19:52:38 -08001706 slarp_reply_out:
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001707 printk(KERN_INFO "%s: got invalid slarp reply (%pI4/%pI4) - ignored\n",
1708 lp->netdev->dev->name, addr, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 break;
1710 case CISCO_SLARP_KEEPALIVE:
1711 period = (int)((jiffies - lp->cisco_last_slarp_in
Joe Perches475be4d2012-02-19 19:52:38 -08001712 + HZ / 2 - 1) / HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 if (lp->cisco_debserint &&
Joe Perches475be4d2012-02-19 19:52:38 -08001714 (period != lp->cisco_keepalive_period) &&
1715 lp->cisco_last_slarp_in) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 printk(KERN_DEBUG "%s: Keepalive period mismatch - "
Joe Perches475be4d2012-02-19 19:52:38 -08001717 "is %d but should be %d.\n",
1718 lp->netdev->dev->name, period,
1719 lp->cisco_keepalive_period);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 }
1721 lp->cisco_last_slarp_in = jiffies;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001722 my_seq = be32_to_cpup((__be32 *)(p + 0));
1723 your_seq = be32_to_cpup((__be32 *)(p + 4));
Harvey Harrison00bcd522008-11-13 22:41:29 -08001724 p += 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 lp->cisco_yourseq = my_seq;
1726 lp->cisco_mineseen = your_seq;
1727 break;
1728 }
1729}
1730
1731static void
1732isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
1733{
1734 unsigned char *p;
Joe Perches475be4d2012-02-19 19:52:38 -08001735 u8 addr;
1736 u8 ctrl;
1737 u16 type;
1738
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 if (skb->len < 4)
1740 goto out_free;
1741
1742 p = skb->data;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001743 addr = *(u8 *)(p + 0);
1744 ctrl = *(u8 *)(p + 1);
1745 type = be16_to_cpup((__be16 *)(p + 2));
1746 p += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 skb_pull(skb, 4);
Joe Perches475be4d2012-02-19 19:52:38 -08001748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
1750 printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001751 lp->netdev->dev->name, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752 goto out_free;
1753 }
1754 if (ctrl != CISCO_CTRL) {
1755 printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001756 lp->netdev->dev->name, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 goto out_free;
1758 }
1759
1760 switch (type) {
1761 case CISCO_TYPE_SLARP:
1762 isdn_net_ciscohdlck_slarp_in(lp, skb);
1763 goto out_free;
1764 case CISCO_TYPE_CDP:
1765 if (lp->cisco_debserint)
1766 printk(KERN_DEBUG "%s: Received CDP packet. use "
Joe Perches475be4d2012-02-19 19:52:38 -08001767 "\"no cdp enable\" on cisco.\n",
1768 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 goto out_free;
1770 default:
1771 /* no special cisco protocol */
1772 skb->protocol = htons(type);
1773 netif_rx(skb);
1774 return;
1775 }
1776
Joe Perches475be4d2012-02-19 19:52:38 -08001777out_free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 kfree_skb(skb);
1779}
1780
1781/*
1782 * Got a packet from ISDN-Channel.
1783 */
1784static void
1785isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
1786{
Joe Perchesa17531f2010-11-15 11:12:24 +00001787 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 isdn_net_local *olp = lp; /* original 'lp' */
1789#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001790 struct concap_proto *cprot = lp->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791#endif
1792 lp->transcount += skb->len;
1793
1794 lp->stats.rx_packets++;
1795 lp->stats.rx_bytes += skb->len;
1796 if (lp->master) {
1797 /* Bundling: If device is a slave-device, deliver to master, also
1798 * handle master's statistics and hangup-timeout
1799 */
1800 ndev = lp->master;
Joe Perchesa17531f2010-11-15 11:12:24 +00001801 lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 lp->stats.rx_packets++;
1803 lp->stats.rx_bytes += skb->len;
1804 }
1805 skb->dev = ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806 skb->pkt_type = PACKET_HOST;
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -07001807 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808#ifdef ISDN_DEBUG_NET_DUMP
1809 isdn_dumppkt("R:", skb->data, skb->len, 40);
1810#endif
1811 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -08001812 case ISDN_NET_ENCAP_ETHER:
1813 /* Ethernet over ISDN */
1814 olp->huptimer = 0;
1815 lp->huptimer = 0;
1816 skb->protocol = isdn_net_type_trans(skb, ndev);
1817 break;
1818 case ISDN_NET_ENCAP_UIHDLC:
1819 /* HDLC with UI-frame (for ispa with -h1 option) */
1820 olp->huptimer = 0;
1821 lp->huptimer = 0;
1822 skb_pull(skb, 2);
1823 /* Fall through */
1824 case ISDN_NET_ENCAP_RAWIP:
1825 /* RAW-IP without MAC-Header */
1826 olp->huptimer = 0;
1827 lp->huptimer = 0;
1828 skb->protocol = htons(ETH_P_IP);
1829 break;
1830 case ISDN_NET_ENCAP_CISCOHDLCK:
1831 isdn_net_ciscohdlck_receive(lp, skb);
1832 return;
1833 case ISDN_NET_ENCAP_CISCOHDLC:
1834 /* CISCO-HDLC IP with type field and fake I-frame-header */
1835 skb_pull(skb, 2);
1836 /* Fall through */
1837 case ISDN_NET_ENCAP_IPTYP:
1838 /* IP with type field */
1839 olp->huptimer = 0;
1840 lp->huptimer = 0;
1841 skb->protocol = *(__be16 *)&(skb->data[0]);
1842 skb_pull(skb, 2);
1843 if (*(unsigned short *) skb->data == 0xFFFF)
1844 skb->protocol = htons(ETH_P_802_3);
1845 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -08001847 case ISDN_NET_ENCAP_SYNCPPP:
1848 /* huptimer is done in isdn_ppp_push_higher */
1849 isdn_ppp_receive(lp->netdev, olp, skb);
1850 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851#endif
1852
Joe Perches475be4d2012-02-19 19:52:38 -08001853 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001855 /* try if there are generic sync_device receiver routines */
1856 if (cprot) if (cprot->pops)
1857 if (cprot->pops->data_ind) {
1858 cprot->pops->data_ind(cprot, skb);
1859 return;
1860 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -08001862 printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
1863 lp->netdev->dev->name);
1864 kfree_skb(skb);
1865 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866 }
1867
1868 netif_rx(skb);
1869 return;
1870}
1871
1872/*
1873 * A packet arrived via ISDN. Search interface-chain for a corresponding
1874 * interface. If found, deliver packet to receiver-function and return 1,
1875 * else return 0.
1876 */
1877int
1878isdn_net_rcv_skb(int idx, struct sk_buff *skb)
1879{
1880 isdn_net_dev *p = dev->rx_netdev[idx];
1881
1882 if (p) {
1883 isdn_net_local *lp = p->local;
1884 if ((lp->flags & ISDN_NET_CONNECTED) &&
1885 (!lp->dialstate)) {
Karsten Keild62a38d2007-10-08 20:37:11 -07001886 isdn_net_receive(p->dev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887 return 1;
1888 }
1889 }
1890 return 0;
1891}
1892
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893/*
1894 * build an header
1895 * depends on encaps that is being used.
1896 */
1897
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001898static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
1899 unsigned short type,
1900 const void *daddr, const void *saddr, unsigned plen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901{
Wang Chen838361f2008-12-03 15:49:46 -08001902 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 unsigned char *p;
Dan Carpenter5a46e0f2012-02-09 00:46:47 +00001904 int len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001905
1906 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -08001907 case ISDN_NET_ENCAP_ETHER:
1908 len = eth_header(skb, dev, type, daddr, saddr, plen);
1909 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -08001911 case ISDN_NET_ENCAP_SYNCPPP:
1912 /* stick on a fake header to keep fragmentation code happy. */
1913 len = IPPP_MAX_HEADER;
1914 skb_push(skb, len);
1915 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916#endif
Joe Perches475be4d2012-02-19 19:52:38 -08001917 case ISDN_NET_ENCAP_RAWIP:
1918 printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
1919 len = 0;
1920 break;
1921 case ISDN_NET_ENCAP_IPTYP:
1922 /* ethernet type field */
1923 *((__be16 *)skb_push(skb, 2)) = htons(type);
1924 len = 2;
1925 break;
1926 case ISDN_NET_ENCAP_UIHDLC:
1927 /* HDLC with UI-Frames (for ispa with -h1 option) */
1928 *((__be16 *)skb_push(skb, 2)) = htons(0x0103);
1929 len = 2;
1930 break;
1931 case ISDN_NET_ENCAP_CISCOHDLC:
1932 case ISDN_NET_ENCAP_CISCOHDLCK:
1933 p = skb_push(skb, 4);
1934 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1935 *(u8 *)(p + 1) = CISCO_CTRL;
1936 *(__be16 *)(p + 2) = cpu_to_be16(type);
1937 p += 4;
1938 len = 4;
1939 break;
1940#ifdef CONFIG_ISDN_X25
1941 default:
1942 /* try if there are generic concap protocol routines */
1943 if (lp->netdev->cprot) {
1944 printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 len = 0;
1946 break;
Joe Perches475be4d2012-02-19 19:52:38 -08001947 }
1948 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001949#endif /* CONFIG_ISDN_X25 */
1950 }
1951 return len;
1952}
1953
1954/* We don't need to send arp, because we have point-to-point connections. */
1955static int
1956isdn_net_rebuild_header(struct sk_buff *skb)
1957{
1958 struct net_device *dev = skb->dev;
Wang Chen838361f2008-12-03 15:49:46 -08001959 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 int ret = 0;
1961
1962 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
1963 struct ethhdr *eth = (struct ethhdr *) skb->data;
1964
1965 /*
1966 * Only ARP/IP is currently supported
1967 */
1968
1969 if (eth->h_proto != htons(ETH_P_IP)) {
1970 printk(KERN_WARNING
1971 "isdn_net: %s don't know how to resolve type %d addresses?\n",
1972 dev->name, (int) eth->h_proto);
1973 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
1974 return 0;
1975 }
1976 /*
1977 * Try to get ARP to resolve the header.
1978 */
1979#ifdef CONFIG_INET
1980 ret = arp_find(eth->h_dest, skb);
1981#endif
1982 }
1983 return ret;
1984}
1985
David S. Millere69dd332011-07-12 23:28:12 -07001986static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
1987 __be16 type)
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001988{
1989 const struct net_device *dev = neigh->dev;
Wang Chen838361f2008-12-03 15:49:46 -08001990 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001991
1992 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
David S. Millere69dd332011-07-12 23:28:12 -07001993 return eth_header_cache(neigh, hh, type);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001994 return -1;
1995}
1996
1997static void isdn_header_cache_update(struct hh_cache *hh,
1998 const struct net_device *dev,
1999 const unsigned char *haddr)
2000{
Wang Chen838361f2008-12-03 15:49:46 -08002001 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002002 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
Harvey Harrisonc19d0362008-11-20 04:10:51 -08002003 eth_header_cache_update(hh, dev, haddr);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002004}
2005
2006static const struct header_ops isdn_header_ops = {
2007 .create = isdn_net_header,
2008 .rebuild = isdn_net_rebuild_header,
2009 .cache = isdn_header_cache,
2010 .cache_update = isdn_header_cache_update,
2011};
2012
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013/*
2014 * Interface-setup. (just after registering a new interface)
2015 */
2016static int
2017isdn_net_init(struct net_device *ndev)
2018{
2019 ushort max_hlhdr_len = 0;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002020 int drvidx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 /*
2023 * up till binding we ask the protocol layer to reserve as much
2024 * as we might need for HL layer
2025 */
2026
2027 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2028 if (dev->drv[drvidx])
2029 if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
2030 max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
2031
2032 ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 return 0;
2034}
2035
2036static void
2037isdn_net_swapbind(int drvidx)
2038{
2039 isdn_net_dev *p;
2040
2041#ifdef ISDN_DEBUG_NET_ICALL
2042 printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
2043#endif
2044 p = dev->netdev;
2045 while (p) {
2046 if (p->local->pre_device == drvidx)
2047 switch (p->local->pre_channel) {
Joe Perches475be4d2012-02-19 19:52:38 -08002048 case 0:
2049 p->local->pre_channel = 1;
2050 break;
2051 case 1:
2052 p->local->pre_channel = 0;
2053 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 }
2055 p = (isdn_net_dev *) p->next;
2056 }
2057}
2058
2059static void
2060isdn_net_swap_usage(int i1, int i2)
2061{
2062 int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
2063 int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
2064
2065#ifdef ISDN_DEBUG_NET_ICALL
2066 printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
2067#endif
2068 dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
2069 dev->usage[i1] |= u2;
2070 dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
2071 dev->usage[i2] |= u1;
2072 isdn_info_update();
2073}
2074
2075/*
2076 * An incoming call-request has arrived.
2077 * Search the interface-chain for an appropriate interface.
2078 * If found, connect the interface to the ISDN-channel and initiate
2079 * D- and B-Channel-setup. If secure-flag is set, accept only
2080 * configured phone-numbers. If callback-flag is set, initiate
2081 * callback-dialing.
2082 *
2083 * Return-Value: 0 = No appropriate interface for this call.
2084 * 1 = Call accepted
2085 * 2 = Reject call, wait cbdelay, then call back
2086 * 3 = Reject call
2087 * 4 = Wait cbdelay, then call back
2088 * 5 = No appropriate interface for this call,
2089 * would eventually match if CID was longer.
2090 */
2091
2092int
2093isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
2094{
2095 char *eaz;
2096 int si1;
2097 int si2;
2098 int ematch;
2099 int wret;
2100 int swapped;
2101 int sidx = 0;
2102 u_long flags;
2103 isdn_net_dev *p;
2104 isdn_net_phone *n;
Karsten Keil0f138642007-11-22 12:43:13 +01002105 char nr[ISDN_MSNLEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106 char *my_eaz;
2107
2108 /* Search name in netdev-chain */
2109 if (!setup->phone[0]) {
2110 nr[0] = '0';
2111 nr[1] = '\0';
2112 printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
2113 } else
Karsten Keil0f138642007-11-22 12:43:13 +01002114 strlcpy(nr, setup->phone, ISDN_MSNLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 si1 = (int) setup->si1;
2116 si2 = (int) setup->si2;
2117 if (!setup->eazmsn[0]) {
2118 printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
2119 eaz = "0";
2120 } else
2121 eaz = setup->eazmsn;
2122 if (dev->net_verbose > 1)
2123 printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
2124 /* Accept DATA and VOICE calls at this stage
2125 * local eaz is checked later for allowed call types
2126 */
2127 if ((si1 != 7) && (si1 != 1)) {
2128 if (dev->net_verbose > 1)
2129 printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
2130 return 0;
2131 }
2132 n = (isdn_net_phone *) 0;
2133 p = dev->netdev;
2134 ematch = wret = swapped = 0;
2135#ifdef ISDN_DEBUG_NET_ICALL
2136 printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
Joe Perches475be4d2012-02-19 19:52:38 -08002137 dev->usage[idx]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138#endif
2139 while (p) {
2140 int matchret;
2141 isdn_net_local *lp = p->local;
2142
2143 /* If last check has triggered as binding-swap, revert it */
2144 switch (swapped) {
Joe Perches475be4d2012-02-19 19:52:38 -08002145 case 2:
2146 isdn_net_swap_usage(idx, sidx);
2147 /* fall through */
2148 case 1:
2149 isdn_net_swapbind(di);
2150 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 }
2152 swapped = 0;
Joe Perches475be4d2012-02-19 19:52:38 -08002153 /* check acceptable call types for DOV */
2154 my_eaz = isdn_map_eaz2msn(lp->msn, di);
2155 if (si1 == 1) { /* it's a DOV call, check if we allow it */
2156 if (*my_eaz == 'v' || *my_eaz == 'V' ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 *my_eaz == 'b' || *my_eaz == 'B')
Joe Perches475be4d2012-02-19 19:52:38 -08002158 my_eaz++; /* skip to allow a match */
2159 else
2160 my_eaz = NULL; /* force non match */
2161 } else { /* it's a DATA call, check if we allow it */
2162 if (*my_eaz == 'b' || *my_eaz == 'B')
2163 my_eaz++; /* skip to allow a match */
2164 }
2165 if (my_eaz)
2166 matchret = isdn_msncmp(eaz, my_eaz);
2167 else
2168 matchret = 1;
2169 if (!matchret)
2170 ematch = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
2172 /* Remember if more numbers eventually can match */
2173 if (matchret > wret)
2174 wret = matchret;
2175#ifdef ISDN_DEBUG_NET_ICALL
2176 printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002177 p->dev->name, lp->msn, lp->flags, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178#endif
2179 if ((!matchret) && /* EAZ is matching */
2180 (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
2181 (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
2182 ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
2183 (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
Joe Perches475be4d2012-02-19 19:52:38 -08002184 )))
2185 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186#ifdef ISDN_DEBUG_NET_ICALL
2187 printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
2188 lp->pre_device, lp->pre_channel);
2189#endif
2190 if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
2191 if ((lp->pre_channel != ch) ||
2192 (lp->pre_device != di)) {
2193 /* Here we got a problem:
2194 * If using an ICN-Card, an incoming call is always signaled on
2195 * on the first channel of the card, if both channels are
2196 * down. However this channel may be bound exclusive. If the
2197 * second channel is free, this call should be accepted.
2198 * The solution is horribly but it runs, so what:
2199 * We exchange the exclusive bindings of the two channels, the
2200 * corresponding variables in the interface-structs.
2201 */
2202 if (ch == 0) {
2203 sidx = isdn_dc2minor(di, 1);
2204#ifdef ISDN_DEBUG_NET_ICALL
2205 printk(KERN_DEBUG "n_fi: ch is 0\n");
2206#endif
2207 if (USG_NONE(dev->usage[sidx])) {
2208 /* Second Channel is free, now see if it is bound
2209 * exclusive too. */
2210 if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
2211#ifdef ISDN_DEBUG_NET_ICALL
2212 printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
2213#endif
2214 /* Yes, swap bindings only, if the original
2215 * binding is bound to channel 1 of this driver */
2216 if ((lp->pre_device == di) &&
2217 (lp->pre_channel == 1)) {
2218 isdn_net_swapbind(di);
2219 swapped = 1;
2220 } else {
2221 /* ... else iterate next device */
2222 p = (isdn_net_dev *) p->next;
2223 continue;
2224 }
2225 } else {
2226#ifdef ISDN_DEBUG_NET_ICALL
2227 printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
2228#endif
2229 /* No, swap always and swap excl-usage also */
2230 isdn_net_swap_usage(idx, sidx);
2231 isdn_net_swapbind(di);
2232 swapped = 2;
2233 }
2234 /* Now check for exclusive binding again */
2235#ifdef ISDN_DEBUG_NET_ICALL
2236 printk(KERN_DEBUG "n_fi: final check\n");
2237#endif
2238 if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
2239 ((lp->pre_channel != ch) ||
2240 (lp->pre_device != di))) {
2241#ifdef ISDN_DEBUG_NET_ICALL
2242 printk(KERN_DEBUG "n_fi: final check failed\n");
2243#endif
2244 p = (isdn_net_dev *) p->next;
2245 continue;
2246 }
2247 }
2248 } else {
2249 /* We are already on the second channel, so nothing to do */
2250#ifdef ISDN_DEBUG_NET_ICALL
2251 printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
2252#endif
2253 }
2254 }
2255 }
2256#ifdef ISDN_DEBUG_NET_ICALL
2257 printk(KERN_DEBUG "n_fi: match2\n");
2258#endif
2259 n = lp->phone[0];
2260 if (lp->flags & ISDN_NET_SECURE) {
2261 while (n) {
2262 if (!isdn_msncmp(nr, n->num))
2263 break;
2264 n = (isdn_net_phone *) n->next;
2265 }
2266 }
2267 if (n || (!(lp->flags & ISDN_NET_SECURE))) {
2268#ifdef ISDN_DEBUG_NET_ICALL
2269 printk(KERN_DEBUG "n_fi: match3\n");
2270#endif
2271 /* matching interface found */
2272
2273 /*
2274 * Is the state STOPPED?
2275 * If so, no dialin is allowed,
2276 * so reject actively.
2277 * */
2278 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2279 printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002280 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 return 3;
2282 }
2283 /*
2284 * Is the interface up?
2285 * If not, reject the call actively.
2286 */
2287 if (!isdn_net_device_started(p)) {
2288 printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002289 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 return 3;
2291 }
2292 /* Interface is up, now see if it's a slave. If so, see if
2293 * it's master and parent slave is online. If not, reject the call.
2294 */
2295 if (lp->master) {
Wang Chen838361f2008-12-03 15:49:46 -08002296 isdn_net_local *mlp = ISDN_MASTER_PRIV(lp);
Karsten Keilfaca94f2007-10-15 02:11:44 -07002297 printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
2298 printk(KERN_DEBUG "master=%s\n", lp->master->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 if (mlp->flags & ISDN_NET_CONNECTED) {
2300 printk(KERN_DEBUG "master online\n");
2301 /* Master is online, find parent-slave (master if first slave) */
2302 while (mlp->slave) {
Wang Chen838361f2008-12-03 15:49:46 -08002303 if (ISDN_SLAVE_PRIV(mlp) == lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 break;
Wang Chen838361f2008-12-03 15:49:46 -08002305 mlp = ISDN_SLAVE_PRIV(mlp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 }
2307 } else
2308 printk(KERN_DEBUG "master offline\n");
2309 /* Found parent, if it's offline iterate next device */
2310 printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
2311 if (!(mlp->flags & ISDN_NET_CONNECTED)) {
2312 p = (isdn_net_dev *) p->next;
2313 continue;
2314 }
Joe Perches475be4d2012-02-19 19:52:38 -08002315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 if (lp->flags & ISDN_NET_CALLBACK) {
2317 int chi;
2318 /*
2319 * Is the state MANUAL?
2320 * If so, no callback can be made,
2321 * so reject actively.
2322 * */
2323 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2324 printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002325 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 return 3;
2327 }
2328 printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002329 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 if (lp->phone[1]) {
2331 /* Grab a free ISDN-Channel */
2332 spin_lock_irqsave(&dev->lock, flags);
Joe Perches475be4d2012-02-19 19:52:38 -08002333 if ((chi =
2334 isdn_get_free_channel(
2335 ISDN_USAGE_NET,
2336 lp->l2_proto,
2337 lp->l3_proto,
2338 lp->pre_device,
2339 lp->pre_channel,
2340 lp->msn)
2341 ) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342
Karsten Keilfaca94f2007-10-15 02:11:44 -07002343 printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002344 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 spin_unlock_irqrestore(&dev->lock, flags);
2346 return 0;
2347 }
2348 /* Setup dialstate. */
2349 lp->dtimer = 0;
2350 lp->dialstate = 11;
2351 /* Connect interface with channel */
2352 isdn_net_bind_channel(lp, chi);
2353#ifdef CONFIG_ISDN_PPP
2354 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2355 if (isdn_ppp_bind(lp) < 0) {
2356 spin_unlock_irqrestore(&dev->lock, flags);
2357 isdn_net_unbind_channel(lp);
2358 return 0;
2359 }
2360#endif
2361 spin_unlock_irqrestore(&dev->lock, flags);
2362 /* Initiate dialing by returning 2 or 4 */
2363 return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
2364 } else
Karsten Keilfaca94f2007-10-15 02:11:44 -07002365 printk(KERN_WARNING "isdn_net: %s: No phone number\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002366 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 return 0;
2368 } else {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002369 printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002370 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 /* if this interface is dialing, it does it probably on a different
2372 device, so free this device */
2373 if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
2374#ifdef CONFIG_ISDN_PPP
2375 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2376 isdn_ppp_free(lp);
2377#endif
2378 isdn_net_lp_disconnected(lp);
2379 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
Joe Perches475be4d2012-02-19 19:52:38 -08002380 ISDN_USAGE_NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
2382 spin_lock_irqsave(&dev->lock, flags);
2383 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2384 dev->usage[idx] |= ISDN_USAGE_NET;
2385 strcpy(dev->num[idx], nr);
2386 isdn_info_update();
2387 dev->st_netdev[idx] = lp->netdev;
2388 lp->isdn_device = di;
2389 lp->isdn_channel = ch;
2390 lp->ppp_slot = -1;
2391 lp->flags |= ISDN_NET_CONNECTED;
2392 lp->dialstate = 7;
2393 lp->dtimer = 0;
2394 lp->outgoing = 0;
2395 lp->huptimer = 0;
2396 lp->hupflags |= ISDN_WAITCHARGE;
2397 lp->hupflags &= ~ISDN_HAVECHARGE;
2398#ifdef CONFIG_ISDN_PPP
2399 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
2400 if (isdn_ppp_bind(lp) < 0) {
2401 isdn_net_unbind_channel(lp);
2402 spin_unlock_irqrestore(&dev->lock, flags);
2403 return 0;
2404 }
2405 }
2406#endif
2407 spin_unlock_irqrestore(&dev->lock, flags);
2408 return 1;
2409 }
2410 }
2411 }
2412 p = (isdn_net_dev *) p->next;
2413 }
2414 /* If none of configured EAZ/MSN matched and not verbose, be silent */
2415 if (!ematch || dev->net_verbose)
2416 printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
Joe Perches475be4d2012-02-19 19:52:38 -08002417 return (wret == 2) ? 5 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418}
2419
2420/*
2421 * Search list of net-interfaces for an interface with given name.
2422 */
2423isdn_net_dev *
2424isdn_net_findif(char *name)
2425{
2426 isdn_net_dev *p = dev->netdev;
2427
2428 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002429 if (!strcmp(p->dev->name, name))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 return p;
2431 p = (isdn_net_dev *) p->next;
2432 }
2433 return (isdn_net_dev *) NULL;
2434}
2435
2436/*
2437 * Force a net-interface to dial out.
2438 * This is called from the userlevel-routine below or
2439 * from isdn_net_start_xmit().
2440 */
Adrian Bunk3e206b02005-06-25 14:58:35 -07002441static int
Joe Perches475be4d2012-02-19 19:52:38 -08002442isdn_net_force_dial_lp(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443{
2444 if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
2445 int chi;
2446 if (lp->phone[1]) {
2447 ulong flags;
2448
2449 /* Grab a free ISDN-Channel */
2450 spin_lock_irqsave(&dev->lock, flags);
2451 if ((chi = isdn_get_free_channel(
Joe Perches475be4d2012-02-19 19:52:38 -08002452 ISDN_USAGE_NET,
2453 lp->l2_proto,
2454 lp->l3_proto,
2455 lp->pre_device,
2456 lp->pre_channel,
2457 lp->msn)) < 0) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002458 printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002459 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460 spin_unlock_irqrestore(&dev->lock, flags);
2461 return -EAGAIN;
2462 }
2463 lp->dialstate = 1;
2464 /* Connect interface with channel */
2465 isdn_net_bind_channel(lp, chi);
2466#ifdef CONFIG_ISDN_PPP
2467 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2468 if (isdn_ppp_bind(lp) < 0) {
2469 isdn_net_unbind_channel(lp);
2470 spin_unlock_irqrestore(&dev->lock, flags);
2471 return -EAGAIN;
2472 }
2473#endif
2474 /* Initiate dialing */
2475 spin_unlock_irqrestore(&dev->lock, flags);
2476 isdn_net_dial();
2477 return 0;
2478 } else
2479 return -EINVAL;
2480 } else
2481 return -EBUSY;
2482}
2483
2484/*
2485 * This is called from certain upper protocol layers (multilink ppp
2486 * and x25iface encapsulation module) that want to initiate dialing
2487 * themselves.
2488 */
2489int
Joe Perches475be4d2012-02-19 19:52:38 -08002490isdn_net_dial_req(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491{
2492 /* is there a better error code? */
2493 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
2494
2495 return isdn_net_force_dial_lp(lp);
2496}
2497
2498/*
2499 * Force a net-interface to dial out.
2500 * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
2501 */
2502int
2503isdn_net_force_dial(char *name)
2504{
2505 isdn_net_dev *p = isdn_net_findif(name);
2506
2507 if (!p)
2508 return -ENODEV;
2509 return (isdn_net_force_dial_lp(p->local));
2510}
2511
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002512/* The ISDN-specific entries in the device structure. */
2513static const struct net_device_ops isdn_netdev_ops = {
2514 .ndo_init = isdn_net_init,
2515 .ndo_open = isdn_net_open,
2516 .ndo_stop = isdn_net_close,
2517 .ndo_do_ioctl = isdn_net_ioctl,
2518
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002519 .ndo_start_xmit = isdn_net_start_xmit,
2520 .ndo_get_stats = isdn_net_get_stats,
2521 .ndo_tx_timeout = isdn_net_tx_timeout,
2522};
2523
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524/*
Karsten Keild62a38d2007-10-08 20:37:11 -07002525 * Helper for alloc_netdev()
2526 */
2527static void _isdn_setup(struct net_device *dev)
2528{
Wang Chen838361f2008-12-03 15:49:46 -08002529 isdn_net_local *lp = netdev_priv(dev);
Karsten Keild62a38d2007-10-08 20:37:11 -07002530
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002531 ether_setup(dev);
2532
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002533 /* Setup the generic properties */
Joe Perches475be4d2012-02-19 19:52:38 -08002534 dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Neil Horman550fd082011-07-26 06:05:38 +00002535
2536 /* isdn prepends a header in the tx path, can't share skbs */
2537 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002538 dev->header_ops = NULL;
2539 dev->netdev_ops = &isdn_netdev_ops;
2540
2541 /* for clients with MPPP maybe higher values better */
2542 dev->tx_queue_len = 30;
2543
Karsten Keild62a38d2007-10-08 20:37:11 -07002544 lp->p_encap = ISDN_NET_ENCAP_RAWIP;
2545 lp->magic = ISDN_NET_MAGIC;
2546 lp->last = lp;
2547 lp->next = lp;
2548 lp->isdn_device = -1;
2549 lp->isdn_channel = -1;
2550 lp->pre_device = -1;
2551 lp->pre_channel = -1;
2552 lp->exclusive = -1;
2553 lp->ppp_slot = -1;
2554 lp->pppbind = -1;
2555 skb_queue_head_init(&lp->super_tx_queue);
2556 lp->l2_proto = ISDN_PROTO_L2_X75I;
2557 lp->l3_proto = ISDN_PROTO_L3_TRANS;
2558 lp->triggercps = 6000;
2559 lp->slavedelay = 10 * HZ;
2560 lp->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
2561 lp->onhtime = 10; /* Default hangup-time for saving costs */
2562 lp->dialmax = 1;
2563 /* Hangup before Callback, manual dial */
2564 lp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
2565 lp->cbdelay = 25; /* Wait 5 secs before Callback */
2566 lp->dialtimeout = -1; /* Infinite Dial-Timeout */
2567 lp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
2568 lp->dialstarted = 0; /* Jiffies of last dial-start */
2569 lp->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
2570}
2571
2572/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 * Allocate a new network-interface and initialize its data structures.
2574 */
2575char *
2576isdn_net_new(char *name, struct net_device *master)
2577{
2578 isdn_net_dev *netdev;
2579
2580 /* Avoid creating an existing interface */
2581 if (isdn_net_findif(name)) {
2582 printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
2583 return NULL;
2584 }
Karsten Keild62a38d2007-10-08 20:37:11 -07002585 if (name == NULL)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002586 return NULL;
Burman Yan41f96932006-12-08 02:39:35 -08002587 if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
2589 return NULL;
2590 }
Karsten Keild62a38d2007-10-08 20:37:11 -07002591 netdev->dev = alloc_netdev(sizeof(isdn_net_local), name, _isdn_setup);
2592 if (!netdev->dev) {
2593 printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 kfree(netdev);
2595 return NULL;
2596 }
Wang Chen838361f2008-12-03 15:49:46 -08002597 netdev->local = netdev_priv(netdev->dev);
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 if (master) {
2600 /* Device shall be a slave */
Wang Chen838361f2008-12-03 15:49:46 -08002601 struct net_device *p = MASTER_TO_SLAVE(master);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 struct net_device *q = master;
2603
2604 netdev->local->master = master;
2605 /* Put device at end of slave-chain */
2606 while (p) {
2607 q = p;
Wang Chen838361f2008-12-03 15:49:46 -08002608 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 }
Wang Chen838361f2008-12-03 15:49:46 -08002610 MASTER_TO_SLAVE(q) = netdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 } else {
2612 /* Device shall be a master */
2613 /*
2614 * Watchdog timer (currently) for master only.
2615 */
Karsten Keild62a38d2007-10-08 20:37:11 -07002616 netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
2617 if (register_netdev(netdev->dev) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 printk(KERN_WARNING "isdn_net: Could not register net-device\n");
Karsten Keild62a38d2007-10-08 20:37:11 -07002619 free_netdev(netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 kfree(netdev);
2621 return NULL;
2622 }
2623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 netdev->queue = netdev->local;
2625 spin_lock_init(&netdev->queue_lock);
2626
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 netdev->local->netdev = netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628
David Howellsc4028952006-11-22 14:57:56 +00002629 INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 spin_lock_init(&netdev->local->xmit_lock);
2631
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 /* Put into to netdev-chain */
2633 netdev->next = (void *) dev->netdev;
2634 dev->netdev = netdev;
Karsten Keild62a38d2007-10-08 20:37:11 -07002635 return netdev->dev->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636}
2637
2638char *
2639isdn_net_newslave(char *parm)
2640{
2641 char *p = strchr(parm, ',');
2642 isdn_net_dev *n;
2643 char newname[10];
2644
2645 if (p) {
2646 /* Slave-Name MUST not be empty */
2647 if (!strlen(p + 1))
2648 return NULL;
2649 strcpy(newname, p + 1);
2650 *p = 0;
2651 /* Master must already exist */
2652 if (!(n = isdn_net_findif(parm)))
2653 return NULL;
2654 /* Master must be a real interface, not a slave */
2655 if (n->local->master)
2656 return NULL;
2657 /* Master must not be started yet */
Joe Perches475be4d2012-02-19 19:52:38 -08002658 if (isdn_net_device_started(n))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 return NULL;
Karsten Keild62a38d2007-10-08 20:37:11 -07002660 return (isdn_net_new(newname, n->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 }
2662 return NULL;
2663}
2664
2665/*
2666 * Set interface-parameters.
2667 * Always set all parameters, so the user-level application is responsible
2668 * for not overwriting existing setups. It has to get the current
2669 * setup first, if only selected parameters are to be changed.
2670 */
2671int
Joe Perches475be4d2012-02-19 19:52:38 -08002672isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673{
2674 isdn_net_dev *p = isdn_net_findif(cfg->name);
2675 ulong features;
2676 int i;
2677 int drvidx;
2678 int chidx;
2679 char drvid[25];
2680
2681 if (p) {
2682 isdn_net_local *lp = p->local;
2683
2684 /* See if any registered driver supports the features we want */
2685 features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
2686 ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
2687 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2688 if (dev->drv[i])
2689 if ((dev->drv[i]->interface->features & features) == features)
2690 break;
2691 if (i == ISDN_MAX_DRIVERS) {
2692 printk(KERN_WARNING "isdn_net: No driver with selected features\n");
2693 return -ENODEV;
2694 }
Joe Perches475be4d2012-02-19 19:52:38 -08002695 if (lp->p_encap != cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08002697 struct concap_proto *cprot = p->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698#endif
2699 if (isdn_net_device_started(p)) {
2700 printk(KERN_WARNING "%s: cannot change encap when if is up\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002701 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return -EBUSY;
2703 }
2704#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08002705 if (cprot && cprot->pops)
2706 cprot->pops->proto_del(cprot);
2707 p->cprot = NULL;
2708 lp->dops = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 /* ... , prepare for configuration of new one ... */
Joe Perches475be4d2012-02-19 19:52:38 -08002710 switch (cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711 case ISDN_NET_ENCAP_X25IFACE:
Joe Perches475be4d2012-02-19 19:52:38 -08002712 lp->dops = &isdn_concap_reliable_dl_dops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002713 }
2714 /* ... and allocate new one ... */
Joe Perches475be4d2012-02-19 19:52:38 -08002715 p->cprot = isdn_concap_new(cfg->p_encap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 /* p -> cprot == NULL now if p_encap is not supported
2717 by means of the concap_proto mechanism */
2718 /* the protocol is not configured yet; this will
2719 happen later when isdn_net_reset() is called */
2720#endif
2721 }
Joe Perches475be4d2012-02-19 19:52:38 -08002722 switch (cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 case ISDN_NET_ENCAP_SYNCPPP:
2724#ifndef CONFIG_ISDN_PPP
2725 printk(KERN_WARNING "%s: SyncPPP support not configured\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002726 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 return -EINVAL;
2728#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002729 p->dev->type = ARPHRD_PPP; /* change ARP type */
2730 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731#endif
2732 break;
2733 case ISDN_NET_ENCAP_X25IFACE:
2734#ifndef CONFIG_ISDN_X25
2735 printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
Denis V. Lunevc749b012007-10-15 12:52:20 -07002736 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737 return -EINVAL;
2738#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002739 p->dev->type = ARPHRD_X25; /* change ARP type */
2740 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741#endif
2742 break;
2743 case ISDN_NET_ENCAP_CISCOHDLCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 break;
2745 default:
Joe Perches475be4d2012-02-19 19:52:38 -08002746 if (cfg->p_encap >= 0 &&
2747 cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 break;
2749 printk(KERN_WARNING
2750 "%s: encapsulation protocol %d not supported\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002751 p->dev->name, cfg->p_encap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 return -EINVAL;
2753 }
2754 if (strlen(cfg->drvid)) {
2755 /* A bind has been requested ... */
2756 char *c,
Joe Perches475be4d2012-02-19 19:52:38 -08002757 *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Dan Carpenter5dc55032011-11-24 02:42:09 +00002759 if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
Joe Perches475be4d2012-02-19 19:52:38 -08002760 sizeof(cfg->drvid))
Dan Carpenter5dc55032011-11-24 02:42:09 +00002761 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 drvidx = -1;
2763 chidx = -1;
2764 strcpy(drvid, cfg->drvid);
2765 if ((c = strchr(drvid, ','))) {
2766 /* The channel-number is appended to the driver-Id with a comma */
2767 chidx = (int) simple_strtoul(c + 1, &e, 10);
2768 if (e == c)
2769 chidx = -1;
2770 *c = '\0';
2771 }
2772 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2773 /* Lookup driver-Id in array */
2774 if (!(strcmp(dev->drvid[i], drvid))) {
2775 drvidx = i;
2776 break;
2777 }
2778 if ((drvidx == -1) || (chidx == -1))
2779 /* Either driver-Id or channel-number invalid */
2780 return -ENODEV;
2781 } else {
2782 /* Parameters are valid, so get them */
2783 drvidx = lp->pre_device;
2784 chidx = lp->pre_channel;
2785 }
2786 if (cfg->exclusive > 0) {
2787 unsigned long flags;
2788
2789 /* If binding is exclusive, try to grab the channel */
2790 spin_lock_irqsave(&dev->lock, flags);
2791 if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
Joe Perches475be4d2012-02-19 19:52:38 -08002792 lp->l2_proto, lp->l3_proto, drvidx,
2793 chidx, lp->msn)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 /* Grab failed, because desired channel is in use */
2795 lp->exclusive = -1;
2796 spin_unlock_irqrestore(&dev->lock, flags);
2797 return -EBUSY;
2798 }
2799 /* All went ok, so update isdninfo */
2800 dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2801 isdn_info_update();
2802 spin_unlock_irqrestore(&dev->lock, flags);
2803 lp->exclusive = i;
2804 } else {
2805 /* Non-exclusive binding or unbind. */
2806 lp->exclusive = -1;
2807 if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2808 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2809 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2810 drvidx = -1;
2811 chidx = -1;
2812 }
2813 }
Karsten Keil0f138642007-11-22 12:43:13 +01002814 strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 lp->pre_device = drvidx;
2816 lp->pre_channel = chidx;
2817 lp->onhtime = cfg->onhtime;
2818 lp->charge = cfg->charge;
2819 lp->l2_proto = cfg->l2_proto;
2820 lp->l3_proto = cfg->l3_proto;
2821 lp->cbdelay = cfg->cbdelay;
2822 lp->dialmax = cfg->dialmax;
2823 lp->triggercps = cfg->triggercps;
2824 lp->slavedelay = cfg->slavedelay * HZ;
2825 lp->pppbind = cfg->pppbind;
2826 lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
2827 lp->dialwait = cfg->dialwait * HZ;
2828 if (cfg->secure)
2829 lp->flags |= ISDN_NET_SECURE;
2830 else
2831 lp->flags &= ~ISDN_NET_SECURE;
2832 if (cfg->cbhup)
2833 lp->flags |= ISDN_NET_CBHUP;
2834 else
2835 lp->flags &= ~ISDN_NET_CBHUP;
2836 switch (cfg->callback) {
Joe Perches475be4d2012-02-19 19:52:38 -08002837 case 0:
2838 lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
2839 break;
2840 case 1:
2841 lp->flags |= ISDN_NET_CALLBACK;
2842 lp->flags &= ~ISDN_NET_CBOUT;
2843 break;
2844 case 2:
2845 lp->flags |= ISDN_NET_CBOUT;
2846 lp->flags &= ~ISDN_NET_CALLBACK;
2847 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 }
2849 lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
2850 if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
2851 /* old isdnctrl version, where only 0 or 1 is given */
2852 printk(KERN_WARNING
Joe Perches475be4d2012-02-19 19:52:38 -08002853 "Old isdnctrl version detected! Please update.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
2855 }
2856 else {
2857 lp->flags |= cfg->dialmode; /* turn on selected bits */
2858 }
2859 if (cfg->chargehup)
2860 lp->hupflags |= ISDN_CHARGEHUP;
2861 else
2862 lp->hupflags &= ~ISDN_CHARGEHUP;
2863 if (cfg->ihup)
2864 lp->hupflags |= ISDN_INHUP;
2865 else
2866 lp->hupflags &= ~ISDN_INHUP;
2867 if (cfg->chargeint > 10) {
2868 lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
2869 lp->chargeint = cfg->chargeint * HZ;
2870 }
2871 if (cfg->p_encap != lp->p_encap) {
2872 if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
Karsten Keild62a38d2007-10-08 20:37:11 -07002873 p->dev->header_ops = NULL;
Joe Perches475be4d2012-02-19 19:52:38 -08002874 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875 } else {
Karsten Keild62a38d2007-10-08 20:37:11 -07002876 p->dev->header_ops = &isdn_header_ops;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002877 if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
Karsten Keild62a38d2007-10-08 20:37:11 -07002878 p->dev->flags = IFF_BROADCAST | IFF_MULTICAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002879 else
Joe Perches475be4d2012-02-19 19:52:38 -08002880 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 }
2882 }
2883 lp->p_encap = cfg->p_encap;
2884 return 0;
2885 }
2886 return -ENODEV;
2887}
2888
2889/*
2890 * Perform get-interface-parameters.ioctl
2891 */
2892int
Joe Perches475be4d2012-02-19 19:52:38 -08002893isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894{
2895 isdn_net_dev *p = isdn_net_findif(cfg->name);
2896
2897 if (p) {
2898 isdn_net_local *lp = p->local;
2899
2900 strcpy(cfg->eaz, lp->msn);
2901 cfg->exclusive = lp->exclusive;
2902 if (lp->pre_device >= 0) {
2903 sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
2904 lp->pre_channel);
2905 } else
2906 cfg->drvid[0] = '\0';
2907 cfg->onhtime = lp->onhtime;
2908 cfg->charge = lp->charge;
2909 cfg->l2_proto = lp->l2_proto;
2910 cfg->l3_proto = lp->l3_proto;
2911 cfg->p_encap = lp->p_encap;
2912 cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
2913 cfg->callback = 0;
2914 if (lp->flags & ISDN_NET_CALLBACK)
2915 cfg->callback = 1;
2916 if (lp->flags & ISDN_NET_CBOUT)
2917 cfg->callback = 2;
2918 cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
2919 cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
2920 cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
2921 cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
2922 cfg->cbdelay = lp->cbdelay;
2923 cfg->dialmax = lp->dialmax;
2924 cfg->triggercps = lp->triggercps;
2925 cfg->slavedelay = lp->slavedelay / HZ;
2926 cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
Joe Perches475be4d2012-02-19 19:52:38 -08002927 (lp->chargeint / HZ) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 cfg->pppbind = lp->pppbind;
2929 cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
2930 cfg->dialwait = lp->dialwait / HZ;
Karsten Keilfaca94f2007-10-15 02:11:44 -07002931 if (lp->slave) {
Dan Carpenter84ce9812010-07-10 04:31:11 +00002932 if (strlen(lp->slave->name) >= 10)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002933 strcpy(cfg->slave, "too-long");
2934 else
2935 strcpy(cfg->slave, lp->slave->name);
2936 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 cfg->slave[0] = '\0';
Karsten Keilfaca94f2007-10-15 02:11:44 -07002938 if (lp->master) {
Dan Carpenter84ce9812010-07-10 04:31:11 +00002939 if (strlen(lp->master->name) >= 10)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002940 strcpy(cfg->master, "too-long");
Dan Carpenter84ce9812010-07-10 04:31:11 +00002941 else
2942 strcpy(cfg->master, lp->master->name);
Karsten Keilfaca94f2007-10-15 02:11:44 -07002943 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 cfg->master[0] = '\0';
2945 return 0;
2946 }
2947 return -ENODEV;
2948}
2949
2950/*
2951 * Add a phone-number to an interface.
2952 */
2953int
Joe Perches475be4d2012-02-19 19:52:38 -08002954isdn_net_addphone(isdn_net_ioctl_phone *phone)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955{
2956 isdn_net_dev *p = isdn_net_findif(phone->name);
2957 isdn_net_phone *n;
2958
2959 if (p) {
Robert P. J. Day5cbded52006-12-13 00:35:56 -08002960 if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 return -ENOMEM;
Karsten Keil0f138642007-11-22 12:43:13 +01002962 strlcpy(n->num, phone->phone, sizeof(n->num));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 n->next = p->local->phone[phone->outgoing & 1];
2964 p->local->phone[phone->outgoing & 1] = n;
2965 return 0;
2966 }
2967 return -ENODEV;
2968}
2969
2970/*
2971 * Copy a string of all phone-numbers of an interface to user space.
2972 * This might sleep and must be called with the isdn semaphore down.
2973 */
2974int
Joe Perches475be4d2012-02-19 19:52:38 -08002975isdn_net_getphones(isdn_net_ioctl_phone *phone, char __user *phones)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976{
2977 isdn_net_dev *p = isdn_net_findif(phone->name);
2978 int inout = phone->outgoing & 1;
2979 int more = 0;
2980 int count = 0;
2981 isdn_net_phone *n;
2982
2983 if (!p)
2984 return -ENODEV;
2985 inout &= 1;
2986 for (n = p->local->phone[inout]; n; n = n->next) {
2987 if (more) {
2988 put_user(' ', phones++);
2989 count++;
2990 }
2991 if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
2992 return -EFAULT;
2993 }
2994 phones += strlen(n->num);
2995 count += strlen(n->num);
2996 more = 1;
2997 }
2998 put_user(0, phones);
2999 count++;
3000 return count;
3001}
3002
3003/*
3004 * Copy a string containing the peer's phone number of a connected interface
3005 * to user space.
3006 */
3007int
3008isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
3009{
3010 isdn_net_dev *p = isdn_net_findif(phone->name);
3011 int ch, dv, idx;
3012
Karsten Keilfaca94f2007-10-15 02:11:44 -07003013 if (!p)
3014 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 /*
3016 * Theoretical race: while this executes, the remote number might
3017 * become invalid (hang up) or change (new connection), resulting
Joe Perches475be4d2012-02-19 19:52:38 -08003018 * in (partially) wrong number copied to user. This race
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 * currently ignored.
3020 */
3021 ch = p->local->isdn_channel;
3022 dv = p->local->isdn_device;
Joe Perches475be4d2012-02-19 19:52:38 -08003023 if (ch < 0 && dv < 0)
Karsten Keilfaca94f2007-10-15 02:11:44 -07003024 return -ENOTCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 idx = isdn_dc2minor(dv, ch);
Joe Perches475be4d2012-02-19 19:52:38 -08003026 if (idx < 0)
Karsten Keilfaca94f2007-10-15 02:11:44 -07003027 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 /* for pre-bound channels, we need this extra check */
Karsten Keilfaca94f2007-10-15 02:11:44 -07003029 if (strncmp(dev->num[idx], "???", 3) == 0)
3030 return -ENOTCONN;
3031 strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
3032 phone->outgoing = USG_OUTGOING(dev->usage[idx]);
3033 if (copy_to_user(peer, phone, sizeof(*peer)))
3034 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035 return 0;
3036}
3037/*
3038 * Delete a phone-number from an interface.
3039 */
3040int
Joe Perches475be4d2012-02-19 19:52:38 -08003041isdn_net_delphone(isdn_net_ioctl_phone *phone)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042{
3043 isdn_net_dev *p = isdn_net_findif(phone->name);
3044 int inout = phone->outgoing & 1;
3045 isdn_net_phone *n;
3046 isdn_net_phone *m;
3047
3048 if (p) {
3049 n = p->local->phone[inout];
3050 m = NULL;
3051 while (n) {
3052 if (!strcmp(n->num, phone->phone)) {
3053 if (p->local->dial == n)
3054 p->local->dial = n->next;
3055 if (m)
3056 m->next = n->next;
3057 else
3058 p->local->phone[inout] = n->next;
3059 kfree(n);
3060 return 0;
3061 }
3062 m = n;
3063 n = (isdn_net_phone *) n->next;
3064 }
3065 return -EINVAL;
3066 }
3067 return -ENODEV;
3068}
3069
3070/*
3071 * Delete all phone-numbers of an interface.
3072 */
3073static int
Joe Perches475be4d2012-02-19 19:52:38 -08003074isdn_net_rmallphone(isdn_net_dev *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075{
3076 isdn_net_phone *n;
3077 isdn_net_phone *m;
3078 int i;
3079
3080 for (i = 0; i < 2; i++) {
3081 n = p->local->phone[i];
3082 while (n) {
3083 m = n->next;
3084 kfree(n);
3085 n = m;
3086 }
3087 p->local->phone[i] = NULL;
3088 }
3089 p->local->dial = NULL;
3090 return 0;
3091}
3092
3093/*
3094 * Force a hangup of a network-interface.
3095 */
3096int
3097isdn_net_force_hangup(char *name)
3098{
3099 isdn_net_dev *p = isdn_net_findif(name);
3100 struct net_device *q;
3101
3102 if (p) {
3103 if (p->local->isdn_device < 0)
3104 return 1;
3105 q = p->local->slave;
3106 /* If this interface has slaves, do a hangup for them also. */
3107 while (q) {
3108 isdn_net_hangup(q);
Wang Chen838361f2008-12-03 15:49:46 -08003109 q = MASTER_TO_SLAVE(q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 }
Karsten Keild62a38d2007-10-08 20:37:11 -07003111 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 return 0;
3113 }
3114 return -ENODEV;
3115}
3116
3117/*
3118 * Helper-function for isdn_net_rm: Do the real work.
3119 */
3120static int
Joe Perches475be4d2012-02-19 19:52:38 -08003121isdn_net_realrm(isdn_net_dev *p, isdn_net_dev *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122{
3123 u_long flags;
3124
3125 if (isdn_net_device_started(p)) {
3126 return -EBUSY;
3127 }
3128#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08003129 if (p->cprot && p->cprot->pops)
3130 p->cprot->pops->proto_del(p->cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131#endif
3132 /* Free all phone-entries */
3133 isdn_net_rmallphone(p);
3134 /* If interface is bound exclusive, free channel-usage */
3135 if (p->local->exclusive != -1)
3136 isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
3137 if (p->local->master) {
3138 /* It's a slave-device, so update master's slave-pointer if necessary */
Wang Chen838361f2008-12-03 15:49:46 -08003139 if (((isdn_net_local *) ISDN_MASTER_PRIV(p->local))->slave ==
3140 p->dev)
3141 ((isdn_net_local *)ISDN_MASTER_PRIV(p->local))->slave =
3142 p->local->slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 } else {
3144 /* Unregister only if it's a master-device */
Karsten Keild62a38d2007-10-08 20:37:11 -07003145 unregister_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 }
3147 /* Unlink device from chain */
3148 spin_lock_irqsave(&dev->lock, flags);
3149 if (q)
3150 q->next = p->next;
3151 else
3152 dev->netdev = p->next;
3153 if (p->local->slave) {
3154 /* If this interface has a slave, remove it also */
Karsten Keilfaca94f2007-10-15 02:11:44 -07003155 char *slavename = p->local->slave->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 isdn_net_dev *n = dev->netdev;
3157 q = NULL;
3158 while (n) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003159 if (!strcmp(n->dev->name, slavename)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 spin_unlock_irqrestore(&dev->lock, flags);
3161 isdn_net_realrm(n, q);
3162 spin_lock_irqsave(&dev->lock, flags);
3163 break;
3164 }
3165 q = n;
Karsten Keilfaca94f2007-10-15 02:11:44 -07003166 n = (isdn_net_dev *)n->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 }
3168 }
3169 spin_unlock_irqrestore(&dev->lock, flags);
3170 /* If no more net-devices remain, disable auto-hangup timer */
3171 if (dev->netdev == NULL)
3172 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
Karsten Keild62a38d2007-10-08 20:37:11 -07003173 free_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 kfree(p);
3175
3176 return 0;
3177}
3178
3179/*
3180 * Remove a single network-interface.
3181 */
3182int
3183isdn_net_rm(char *name)
3184{
3185 u_long flags;
3186 isdn_net_dev *p;
3187 isdn_net_dev *q;
3188
3189 /* Search name in netdev-chain */
3190 spin_lock_irqsave(&dev->lock, flags);
3191 p = dev->netdev;
3192 q = NULL;
3193 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003194 if (!strcmp(p->dev->name, name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 spin_unlock_irqrestore(&dev->lock, flags);
3196 return (isdn_net_realrm(p, q));
3197 }
3198 q = p;
3199 p = (isdn_net_dev *) p->next;
3200 }
3201 spin_unlock_irqrestore(&dev->lock, flags);
3202 /* If no more net-devices remain, disable auto-hangup timer */
3203 if (dev->netdev == NULL)
3204 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3205 return -ENODEV;
3206}
3207
3208/*
3209 * Remove all network-interfaces
3210 */
3211int
3212isdn_net_rmall(void)
3213{
3214 u_long flags;
3215 int ret;
3216
3217 /* Walk through netdev-chain */
3218 spin_lock_irqsave(&dev->lock, flags);
3219 while (dev->netdev) {
3220 if (!dev->netdev->local->master) {
3221 /* Remove master-devices only, slaves get removed with their master */
3222 spin_unlock_irqrestore(&dev->lock, flags);
3223 if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
3224 return ret;
3225 }
3226 spin_lock_irqsave(&dev->lock, flags);
3227 }
3228 }
3229 dev->netdev = NULL;
3230 spin_unlock_irqrestore(&dev->lock, flags);
3231 return 0;
3232}