blob: cb8943da4f122f8c3fdf2703d405160ddad309b5 [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 *
12 * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
13 * 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>
21 * for info on the protocol, see
22 * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
23 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/isdn.h>
26#include <net/arp.h>
27#include <net/dst.h>
28#include <net/pkt_sched.h>
29#include <linux/inetdevice.h>
30#include "isdn_common.h"
31#include "isdn_net.h"
32#ifdef CONFIG_ISDN_PPP
33#include "isdn_ppp.h"
34#endif
35#ifdef CONFIG_ISDN_X25
36#include <linux/concap.h>
37#include "isdn_concap.h"
38#endif
39
40
41/*
42 * Outline of new tbusy handling:
43 *
44 * Old method, roughly spoken, consisted of setting tbusy when entering
45 * isdn_net_start_xmit() and at several other locations and clearing
46 * it from isdn_net_start_xmit() thread when sending was successful.
47 *
48 * With 2.3.x multithreaded network core, to prevent problems, tbusy should
49 * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
50 * condition is detected. Other threads (in particular isdn_net_stat_callb())
51 * are only allowed to clear tbusy.
52 *
53 * -HE
54 */
55
56/*
57 * About SOFTNET:
58 * Most of the changes were pretty obvious and basically done by HE already.
59 *
60 * One problem of the isdn net device code is that is uses struct net_device
61 * for masters and slaves. However, only master interface are registered to
62 * the network layer, and therefore, it only makes sense to call netif_*
63 * functions on them.
64 *
65 * --KG
66 */
67
68/*
69 * Find out if the netdevice has been ifup-ed yet.
70 * For slaves, look at the corresponding master.
71 */
72static __inline__ int isdn_net_device_started(isdn_net_dev *n)
73{
74 isdn_net_local *lp = n->local;
75 struct net_device *dev;
76
77 if (lp->master)
78 dev = lp->master;
79 else
Karsten Keild62a38d2007-10-08 20:37:11 -070080 dev = n->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 return netif_running(dev);
82}
83
84/*
85 * wake up the network -> net_device queue.
86 * For slaves, wake the corresponding master interface.
87 */
88static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
89{
90 if (lp->master)
91 netif_wake_queue(lp->master);
92 else
Karsten Keild62a38d2007-10-08 20:37:11 -070093 netif_wake_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070094}
95
96/*
97 * stop the network -> net_device queue.
98 * For slaves, stop the corresponding master interface.
99 */
100static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
101{
102 if (lp->master)
103 netif_stop_queue(lp->master);
104 else
Karsten Keild62a38d2007-10-08 20:37:11 -0700105 netif_stop_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
108/*
109 * find out if the net_device which this lp belongs to (lp can be
110 * master or slave) is busy. It's busy iff all (master and slave)
111 * queues are busy
112 */
113static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
114{
115 isdn_net_local *nlp;
116 isdn_net_dev *nd;
117 unsigned long flags;
118
119 if (!isdn_net_lp_busy(lp))
120 return 0;
121
122 if (lp->master)
Wang Chen838361f2008-12-03 15:49:46 -0800123 nd = ISDN_MASTER_PRIV(lp)->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 else
125 nd = lp->netdev;
126
127 spin_lock_irqsave(&nd->queue_lock, flags);
128 nlp = lp->next;
129 while (nlp != lp) {
130 if (!isdn_net_lp_busy(nlp)) {
131 spin_unlock_irqrestore(&nd->queue_lock, flags);
132 return 0;
133 }
134 nlp = nlp->next;
135 }
136 spin_unlock_irqrestore(&nd->queue_lock, flags);
137 return 1;
138}
139
140static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
141{
142 atomic_inc(&lp->frame_cnt);
143 if (isdn_net_device_busy(lp))
144 isdn_net_device_stop_queue(lp);
145}
146
147static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
148{
149 atomic_dec(&lp->frame_cnt);
150
151 if (!(isdn_net_device_busy(lp))) {
152 if (!skb_queue_empty(&lp->super_tx_queue)) {
153 schedule_work(&lp->tqueue);
154 } else {
155 isdn_net_device_wake_queue(lp);
156 }
157 }
158}
159
160static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
161{
162 atomic_set(&lp->frame_cnt, 0);
163}
164
165/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
166 * to be safe.
167 * For 2.3.x we push it up to 20 secs, because call establishment
168 * (in particular callback) may take such a long time, and we
169 * don't want confusing messages in the log. However, there is a slight
170 * possibility that this large timeout will break other things like MPPP,
171 * which might rely on the tx timeout. If so, we'll find out this way...
172 */
173
174#define ISDN_NET_TX_TIMEOUT (20*HZ)
175
176/* Prototypes */
177
Adrian Bunk3e206b02005-06-25 14:58:35 -0700178static int isdn_net_force_dial_lp(isdn_net_local *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
180
181static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
182static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
183
184char *isdn_net_revision = "$Revision: 1.1.2.2 $";
185
186 /*
187 * Code for raw-networking over ISDN
188 */
189
190static void
191isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
192{
193 if(skb) {
194
195 u_short proto = ntohs(skb->protocol);
196
197 printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
198 dev->name,
199 (reason != NULL) ? reason : "unknown",
200 (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
201
202 dst_link_failure(skb);
203 }
204 else { /* dial not triggered by rawIP packet */
205 printk(KERN_DEBUG "isdn_net: %s: %s\n",
206 dev->name,
207 (reason != NULL) ? reason : "reason unknown");
208 }
209}
210
211static void
212isdn_net_reset(struct net_device *dev)
213{
214#ifdef CONFIG_ISDN_X25
215 struct concap_device_ops * dops =
Wang Chen838361f2008-12-03 15:49:46 -0800216 ((isdn_net_local *) netdev_priv(dev))->dops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 struct concap_proto * cprot =
Wang Chen838361f2008-12-03 15:49:46 -0800218 ((isdn_net_local *) netdev_priv(dev))->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219#endif
220#ifdef CONFIG_ISDN_X25
221 if( cprot && cprot -> pops && dops )
222 cprot -> pops -> restart ( cprot, dev, dops );
223#endif
224}
225
226/* Open/initialize the board. */
227static int
228isdn_net_open(struct net_device *dev)
229{
230 int i;
231 struct net_device *p;
232 struct in_device *in_dev;
233
234 /* moved here from isdn_net_reset, because only the master has an
235 interface associated which is supposed to be started. BTW:
236 we need to call netif_start_queue, not netif_wake_queue here */
237 netif_start_queue(dev);
238
239 isdn_net_reset(dev);
240 /* Fill in the MAC-level header (not needed, but for compatibility... */
241 for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
242 dev->dev_addr[i] = 0xfc;
243 if ((in_dev = dev->ip_ptr) != NULL) {
244 /*
245 * Any address will do - we take the first
246 */
247 struct in_ifaddr *ifa = in_dev->ifa_list;
248 if (ifa != NULL)
249 memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
250 }
251
252 /* If this interface has slaves, start them also */
Wang Chen838361f2008-12-03 15:49:46 -0800253 p = MASTER_TO_SLAVE(dev);
254 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 while (p) {
256 isdn_net_reset(p);
Wang Chen838361f2008-12-03 15:49:46 -0800257 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 }
259 }
260 isdn_lock_drivers();
261 return 0;
262}
263
264/*
265 * Assign an ISDN-channel to a net-interface
266 */
267static void
268isdn_net_bind_channel(isdn_net_local * lp, int idx)
269{
270 lp->flags |= ISDN_NET_CONNECTED;
271 lp->isdn_device = dev->drvmap[idx];
272 lp->isdn_channel = dev->chanmap[idx];
273 dev->rx_netdev[idx] = lp->netdev;
274 dev->st_netdev[idx] = lp->netdev;
275}
276
277/*
278 * unbind a net-interface (resets interface after an error)
279 */
280static void
281isdn_net_unbind_channel(isdn_net_local * lp)
282{
283 skb_queue_purge(&lp->super_tx_queue);
284
285 if (!lp->master) { /* reset only master device */
286 /* Moral equivalent of dev_purge_queues():
287 BEWARE! This chunk of code cannot be called from hardware
288 interrupt handler. I hope it is true. --ANK
289 */
David S. Miller5aa70992008-07-08 22:59:10 -0700290 qdisc_reset_all_tx(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 }
292 lp->dialstate = 0;
293 dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
294 dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
Paul Bollebae58432009-01-14 14:41:00 -0800295 if (lp->isdn_device != -1 && lp->isdn_channel != -1)
296 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
297 ISDN_USAGE_NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 lp->flags &= ~ISDN_NET_CONNECTED;
299 lp->isdn_device = -1;
300 lp->isdn_channel = -1;
301}
302
303/*
304 * Perform auto-hangup and cps-calculation for net-interfaces.
305 *
306 * auto-hangup:
307 * Increment idle-counter (this counter is reset on any incoming or
308 * outgoing packet), if counter exceeds configured limit either do a
309 * hangup immediately or - if configured - wait until just before the next
310 * charge-info.
311 *
312 * cps-calculation (needed for dynamic channel-bundling):
313 * Since this function is called every second, simply reset the
314 * byte-counter of the interface after copying it to the cps-variable.
315 */
Adrian Bunk3e206b02005-06-25 14:58:35 -0700316static unsigned long last_jiffies = -HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317
318void
319isdn_net_autohup(void)
320{
321 isdn_net_dev *p = dev->netdev;
322 int anymore;
323
324 anymore = 0;
325 while (p) {
326 isdn_net_local *l = p->local;
327 if (jiffies == last_jiffies)
328 l->cps = l->transcount;
329 else
330 l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
331 l->transcount = 0;
332 if (dev->net_verbose > 3)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700333 printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
335 anymore = 1;
336 l->huptimer++;
337 /*
338 * if there is some dialmode where timeout-hangup
339 * should _not_ be done, check for that here
340 */
341 if ((l->onhtime) &&
342 (l->huptimer > l->onhtime))
343 {
344 if (l->hupflags & ISDN_MANCHARGE &&
345 l->hupflags & ISDN_CHARGEHUP) {
346 while (time_after(jiffies, l->chargetime + l->chargeint))
347 l->chargetime += l->chargeint;
348 if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
349 if (l->outgoing || l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700350 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 } else if (l->outgoing) {
352 if (l->hupflags & ISDN_CHARGEHUP) {
353 if (l->hupflags & ISDN_WAITCHARGE) {
354 printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700355 p->dev->name, l->hupflags);
Karsten Keild62a38d2007-10-08 20:37:11 -0700356 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
358 printk(KERN_DEBUG
359 "isdn_net: %s: chtime = %lu, chint = %d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700360 p->dev->name, l->chargetime, l->chargeint);
Karsten Keild62a38d2007-10-08 20:37:11 -0700361 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 }
363 } else
Karsten Keild62a38d2007-10-08 20:37:11 -0700364 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365 } else if (l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700366 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 }
368
369 if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
Karsten Keild62a38d2007-10-08 20:37:11 -0700370 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 break;
372 }
373 }
374 p = (isdn_net_dev *) p->next;
375 }
376 last_jiffies = jiffies;
377 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
378}
379
380static void isdn_net_lp_disconnected(isdn_net_local *lp)
381{
382 isdn_net_rm_from_bundle(lp);
383}
384
385/*
386 * Handle status-messages from ISDN-interfacecard.
387 * This function is called from within the main-status-dispatcher
388 * isdn_status_callback, which itself is called from the low-level driver.
389 * Return: 1 = Event handled, 0 = not for us or unknown Event.
390 */
391int
392isdn_net_stat_callback(int idx, isdn_ctrl *c)
393{
394 isdn_net_dev *p = dev->st_netdev[idx];
395 int cmd = c->command;
396
397 if (p) {
398 isdn_net_local *lp = p->local;
399#ifdef CONFIG_ISDN_X25
400 struct concap_proto *cprot = lp->netdev->cprot;
401 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
402#endif
403 switch (cmd) {
404 case ISDN_STAT_BSENT:
405 /* A packet has successfully been sent out */
406 if ((lp->flags & ISDN_NET_CONNECTED) &&
407 (!lp->dialstate)) {
408 isdn_net_dec_frame_cnt(lp);
409 lp->stats.tx_packets++;
410 lp->stats.tx_bytes += c->parm.length;
411 }
412 return 1;
413 case ISDN_STAT_DCONN:
414 /* D-Channel is up */
415 switch (lp->dialstate) {
416 case 4:
417 case 7:
418 case 8:
419 lp->dialstate++;
420 return 1;
421 case 12:
422 lp->dialstate = 5;
423 return 1;
424 }
425 break;
426 case ISDN_STAT_DHUP:
427 /* Either D-Channel-hangup or error during dialout */
428#ifdef CONFIG_ISDN_X25
429 /* If we are not connencted then dialing had
430 failed. If there are generic encap protocol
431 receiver routines signal the closure of
432 the link*/
433
434 if( !(lp->flags & ISDN_NET_CONNECTED)
435 && pops && pops -> disconn_ind )
436 pops -> disconn_ind(cprot);
437#endif /* CONFIG_ISDN_X25 */
438 if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
439 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
440 isdn_net_ciscohdlck_disconnected(lp);
441#ifdef CONFIG_ISDN_PPP
442 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
443 isdn_ppp_free(lp);
444#endif
445 isdn_net_lp_disconnected(lp);
446 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
Karsten Keilfaca94f2007-10-15 02:11:44 -0700447 printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
448 printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 lp->charge);
450 isdn_net_unbind_channel(lp);
451 return 1;
452 }
453 break;
454#ifdef CONFIG_ISDN_X25
455 case ISDN_STAT_BHUP:
456 /* B-Channel-hangup */
457 /* try if there are generic encap protocol
458 receiver routines and signal the closure of
459 the link */
460 if( pops && pops -> disconn_ind ){
461 pops -> disconn_ind(cprot);
462 return 1;
463 }
464 break;
465#endif /* CONFIG_ISDN_X25 */
466 case ISDN_STAT_BCONN:
467 /* B-Channel is up */
468 isdn_net_zero_frame_cnt(lp);
469 switch (lp->dialstate) {
470 case 5:
471 case 6:
472 case 7:
473 case 8:
474 case 9:
475 case 10:
476 case 12:
477 if (lp->dialstate <= 6) {
478 dev->usage[idx] |= ISDN_USAGE_OUTGOING;
479 isdn_info_update();
480 } else
481 dev->rx_netdev[idx] = p;
482 lp->dialstate = 0;
483 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
484 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
485 isdn_net_ciscohdlck_connected(lp);
486 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
487 if (lp->master) { /* is lp a slave? */
Wang Chen838361f2008-12-03 15:49:46 -0800488 isdn_net_dev *nd = ISDN_MASTER_PRIV(lp)->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 isdn_net_add_to_bundle(nd, lp);
490 }
491 }
Karsten Keilfaca94f2007-10-15 02:11:44 -0700492 printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 /* If first Chargeinfo comes before B-Channel connect,
494 * we correct the timestamp here.
495 */
496 lp->chargetime = jiffies;
497
498 /* reset dial-timeout */
499 lp->dialstarted = 0;
500 lp->dialwait_timer = 0;
501
502#ifdef CONFIG_ISDN_PPP
503 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
504 isdn_ppp_wakeup_daemon(lp);
505#endif
506#ifdef CONFIG_ISDN_X25
507 /* try if there are generic concap receiver routines */
508 if( pops )
509 if( pops->connect_ind)
510 pops->connect_ind(cprot);
511#endif /* CONFIG_ISDN_X25 */
512 /* ppp needs to do negotiations first */
513 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
514 isdn_net_device_wake_queue(lp);
515 return 1;
516 }
517 break;
518 case ISDN_STAT_NODCH:
519 /* No D-Channel avail. */
520 if (lp->dialstate == 4) {
521 lp->dialstate--;
522 return 1;
523 }
524 break;
525 case ISDN_STAT_CINF:
526 /* Charge-info from TelCo. Calculate interval between
527 * charge-infos and set timestamp for last info for
528 * usage by isdn_net_autohup()
529 */
530 lp->charge++;
531 if (lp->hupflags & ISDN_HAVECHARGE) {
532 lp->hupflags &= ~ISDN_WAITCHARGE;
533 lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
534 }
535 if (lp->hupflags & ISDN_WAITCHARGE)
536 lp->hupflags |= ISDN_HAVECHARGE;
537 lp->chargetime = jiffies;
538 printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700539 p->dev->name, lp->chargetime);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return 1;
541 }
542 }
543 return 0;
544}
545
546/*
547 * Perform dialout for net-interfaces and timeout-handling for
548 * D-Channel-up and B-Channel-up Messages.
549 * This function is initially called from within isdn_net_start_xmit() or
550 * or isdn_net_find_icall() after initializing the dialstate for an
551 * interface. If further calls are needed, the function schedules itself
552 * for a timer-callback via isdn_timer_function().
553 * The dialstate is also affected by incoming status-messages from
554 * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
555 */
556void
557isdn_net_dial(void)
558{
559 isdn_net_dev *p = dev->netdev;
560 int anymore = 0;
561 int i;
562 isdn_ctrl cmd;
563 u_char *phone_number;
564
565 while (p) {
566 isdn_net_local *lp = p->local;
567
568#ifdef ISDN_DEBUG_NET_DIAL
569 if (lp->dialstate)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700570 printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571#endif
572 switch (lp->dialstate) {
573 case 0:
574 /* Nothing to do for this interface */
575 break;
576 case 1:
577 /* Initiate dialout. Set phone-number-pointer to first number
578 * of interface.
579 */
580 lp->dial = lp->phone[1];
581 if (!lp->dial) {
582 printk(KERN_WARNING "%s: phone number deleted?\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700583 p->dev->name);
Karsten Keild62a38d2007-10-08 20:37:11 -0700584 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 break;
586 }
587 anymore = 1;
588
589 if(lp->dialtimeout > 0)
590 if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
591 lp->dialstarted = jiffies;
592 lp->dialwait_timer = 0;
593 }
594
595 lp->dialstate++;
596 /* Fall through */
597 case 2:
598 /* Prepare dialing. Clear EAZ, then set EAZ. */
599 cmd.driver = lp->isdn_device;
600 cmd.arg = lp->isdn_channel;
601 cmd.command = ISDN_CMD_CLREAZ;
602 isdn_command(&cmd);
603 sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
604 cmd.command = ISDN_CMD_SETEAZ;
605 isdn_command(&cmd);
606 lp->dialretry = 0;
607 anymore = 1;
608 lp->dialstate++;
609 /* Fall through */
610 case 3:
611 /* Setup interface, dial current phone-number, switch to next number.
612 * If list of phone-numbers is exhausted, increment
613 * retry-counter.
614 */
615 if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
616 char *s;
617 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
618 s = "dial suppressed: isdn system stopped";
619 else
620 s = "dial suppressed: dialmode `off'";
Karsten Keild62a38d2007-10-08 20:37:11 -0700621 isdn_net_unreachable(p->dev, NULL, s);
622 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 break;
624 }
625 cmd.driver = lp->isdn_device;
626 cmd.command = ISDN_CMD_SETL2;
627 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
628 isdn_command(&cmd);
629 cmd.driver = lp->isdn_device;
630 cmd.command = ISDN_CMD_SETL3;
631 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
632 isdn_command(&cmd);
633 cmd.driver = lp->isdn_device;
634 cmd.arg = lp->isdn_channel;
635 if (!lp->dial) {
636 printk(KERN_WARNING "%s: phone number deleted?\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700637 p->dev->name);
Karsten Keild62a38d2007-10-08 20:37:11 -0700638 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 break;
640 }
641 if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
642 lp->dialstate = 4;
Karsten Keilfaca94f2007-10-15 02:11:44 -0700643 printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 } else {
645 if(lp->dialtimeout > 0)
646 if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
647 lp->dialwait_timer = jiffies + lp->dialwait;
648 lp->dialstarted = 0;
Karsten Keild62a38d2007-10-08 20:37:11 -0700649 isdn_net_unreachable(p->dev, NULL, "dial: timed out");
650 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 break;
652 }
653
654 cmd.driver = lp->isdn_device;
655 cmd.command = ISDN_CMD_DIAL;
656 cmd.parm.setup.si2 = 0;
657
658 /* check for DOV */
659 phone_number = lp->dial->num;
660 if ((*phone_number == 'v') ||
661 (*phone_number == 'V')) { /* DOV call */
662 cmd.parm.setup.si1 = 1;
663 } else { /* DATA call */
664 cmd.parm.setup.si1 = 7;
665 }
666
667 strcpy(cmd.parm.setup.phone, phone_number);
668 /*
669 * Switch to next number or back to start if at end of list.
670 */
671 if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
672 lp->dial = lp->phone[1];
673 lp->dialretry++;
674
675 if (lp->dialretry > lp->dialmax) {
676 if (lp->dialtimeout == 0) {
677 lp->dialwait_timer = jiffies + lp->dialwait;
678 lp->dialstarted = 0;
Karsten Keild62a38d2007-10-08 20:37:11 -0700679 isdn_net_unreachable(p->dev, NULL, "dial: tried all numbers dialmax times");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
Karsten Keild62a38d2007-10-08 20:37:11 -0700681 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 break;
683 }
684 }
685 sprintf(cmd.parm.setup.eazmsn, "%s",
686 isdn_map_eaz2msn(lp->msn, cmd.driver));
687 i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
688 if (i >= 0) {
689 strcpy(dev->num[i], cmd.parm.setup.phone);
690 dev->usage[i] |= ISDN_USAGE_OUTGOING;
691 isdn_info_update();
692 }
Karsten Keilfaca94f2007-10-15 02:11:44 -0700693 printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 lp->dialretry, cmd.parm.setup.phone,
695 (cmd.parm.setup.si1 == 1) ? "DOV" : "");
696 lp->dtimer = 0;
697#ifdef ISDN_DEBUG_NET_DIAL
698 printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
699 lp->isdn_channel);
700#endif
701 isdn_command(&cmd);
702 }
703 lp->huptimer = 0;
704 lp->outgoing = 1;
705 if (lp->chargeint) {
706 lp->hupflags |= ISDN_HAVECHARGE;
707 lp->hupflags &= ~ISDN_WAITCHARGE;
708 } else {
709 lp->hupflags |= ISDN_WAITCHARGE;
710 lp->hupflags &= ~ISDN_HAVECHARGE;
711 }
712 anymore = 1;
713 lp->dialstate =
714 (lp->cbdelay &&
715 (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
716 break;
717 case 4:
718 /* Wait for D-Channel-connect.
719 * If timeout, switch back to state 3.
720 * Dialmax-handling moved to state 3.
721 */
722 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
723 lp->dialstate = 3;
724 anymore = 1;
725 break;
726 case 5:
727 /* Got D-Channel-Connect, send B-Channel-request */
728 cmd.driver = lp->isdn_device;
729 cmd.arg = lp->isdn_channel;
730 cmd.command = ISDN_CMD_ACCEPTB;
731 anymore = 1;
732 lp->dtimer = 0;
733 lp->dialstate++;
734 isdn_command(&cmd);
735 break;
736 case 6:
737 /* Wait for B- or D-Channel-connect. If timeout,
738 * switch back to state 3.
739 */
740#ifdef ISDN_DEBUG_NET_DIAL
741 printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
742#endif
743 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
744 lp->dialstate = 3;
745 anymore = 1;
746 break;
747 case 7:
748 /* Got incoming Call, setup L2 and L3 protocols,
749 * then wait for D-Channel-connect
750 */
751#ifdef ISDN_DEBUG_NET_DIAL
752 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
753#endif
754 cmd.driver = lp->isdn_device;
755 cmd.command = ISDN_CMD_SETL2;
756 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
757 isdn_command(&cmd);
758 cmd.driver = lp->isdn_device;
759 cmd.command = ISDN_CMD_SETL3;
760 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
761 isdn_command(&cmd);
762 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
Karsten Keild62a38d2007-10-08 20:37:11 -0700763 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 else {
765 anymore = 1;
766 lp->dialstate++;
767 }
768 break;
769 case 9:
770 /* Got incoming D-Channel-Connect, send B-Channel-request */
771 cmd.driver = lp->isdn_device;
772 cmd.arg = lp->isdn_channel;
773 cmd.command = ISDN_CMD_ACCEPTB;
774 isdn_command(&cmd);
775 anymore = 1;
776 lp->dtimer = 0;
777 lp->dialstate++;
778 break;
779 case 8:
780 case 10:
781 /* Wait for B- or D-channel-connect */
782#ifdef ISDN_DEBUG_NET_DIAL
783 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
784#endif
785 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
Karsten Keild62a38d2007-10-08 20:37:11 -0700786 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 else
788 anymore = 1;
789 break;
790 case 11:
791 /* Callback Delay */
792 if (lp->dtimer++ > lp->cbdelay)
793 lp->dialstate = 1;
794 anymore = 1;
795 break;
796 case 12:
797 /* Remote does callback. Hangup after cbdelay, then wait for incoming
798 * call (in state 4).
799 */
800 if (lp->dtimer++ > lp->cbdelay)
801 {
Karsten Keilfaca94f2007-10-15 02:11:44 -0700802 printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 lp->dtimer = 0;
804 lp->dialstate = 4;
805 cmd.driver = lp->isdn_device;
806 cmd.command = ISDN_CMD_HANGUP;
807 cmd.arg = lp->isdn_channel;
808 isdn_command(&cmd);
809 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
810 }
811 anymore = 1;
812 break;
813 default:
814 printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700815 lp->dialstate, p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 }
817 p = (isdn_net_dev *) p->next;
818 }
819 isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
820}
821
822/*
823 * Perform hangup for a net-interface.
824 */
825void
826isdn_net_hangup(struct net_device *d)
827{
Wang Chen838361f2008-12-03 15:49:46 -0800828 isdn_net_local *lp = (isdn_net_local *) netdev_priv(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 isdn_ctrl cmd;
830#ifdef CONFIG_ISDN_X25
831 struct concap_proto *cprot = lp->netdev->cprot;
832 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
833#endif
834
835 if (lp->flags & ISDN_NET_CONNECTED) {
836 if (lp->slave != NULL) {
Wang Chen838361f2008-12-03 15:49:46 -0800837 isdn_net_local *slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 if (slp->flags & ISDN_NET_CONNECTED) {
839 printk(KERN_INFO
840 "isdn_net: hang up slave %s before %s\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700841 lp->slave->name, d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 isdn_net_hangup(lp->slave);
843 }
844 }
Karsten Keilfaca94f2007-10-15 02:11:44 -0700845 printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846#ifdef CONFIG_ISDN_PPP
847 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
848 isdn_ppp_free(lp);
849#endif
850 isdn_net_lp_disconnected(lp);
851#ifdef CONFIG_ISDN_X25
852 /* try if there are generic encap protocol
853 receiver routines and signal the closure of
854 the link */
855 if( pops && pops -> disconn_ind )
856 pops -> disconn_ind(cprot);
857#endif /* CONFIG_ISDN_X25 */
858
859 cmd.driver = lp->isdn_device;
860 cmd.command = ISDN_CMD_HANGUP;
861 cmd.arg = lp->isdn_channel;
862 isdn_command(&cmd);
Karsten Keilfaca94f2007-10-15 02:11:44 -0700863 printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
865 }
866 isdn_net_unbind_channel(lp);
867}
868
869typedef struct {
Harvey Harrisonc19d0362008-11-20 04:10:51 -0800870 __be16 source;
871 __be16 dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872} ip_ports;
873
874static void
875isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
876{
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -0700877 /* hopefully, this was set correctly */
878 const u_char *p = skb_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 unsigned short proto = ntohs(skb->protocol);
880 int data_ofs;
881 ip_ports *ipp;
882 char addinfo[100];
883
884 addinfo[0] = '\0';
885 /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
Arnaldo Carvalho de Melo27a884d2007-04-19 20:29:13 -0700886 if (p < skb->data || skb->network_header >= skb->tail) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 /* fall back to old isdn_net_log_packet method() */
888 char * buf = skb->data;
889
Karsten Keilfaca94f2007-10-15 02:11:44 -0700890 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 -0700891 p = buf;
892 proto = ETH_P_IP;
893 switch (lp->p_encap) {
894 case ISDN_NET_ENCAP_IPTYP:
Harvey Harrison00bcd522008-11-13 22:41:29 -0800895 proto = ntohs(*(__be16 *)&buf[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 p = &buf[2];
897 break;
898 case ISDN_NET_ENCAP_ETHER:
Harvey Harrison00bcd522008-11-13 22:41:29 -0800899 proto = ntohs(*(__be16 *)&buf[12]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 p = &buf[14];
901 break;
902 case ISDN_NET_ENCAP_CISCOHDLC:
Harvey Harrison00bcd522008-11-13 22:41:29 -0800903 proto = ntohs(*(__be16 *)&buf[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 p = &buf[4];
905 break;
906#ifdef CONFIG_ISDN_PPP
907 case ISDN_NET_ENCAP_SYNCPPP:
908 proto = ntohs(skb->protocol);
909 p = &buf[IPPP_MAX_HEADER];
910 break;
911#endif
912 }
913 }
914 data_ofs = ((p[0] & 15) * 4);
915 switch (proto) {
916 case ETH_P_IP:
917 switch (p[9]) {
918 case 1:
919 strcpy(addinfo, " ICMP");
920 break;
921 case 2:
922 strcpy(addinfo, " IGMP");
923 break;
924 case 4:
925 strcpy(addinfo, " IPIP");
926 break;
927 case 6:
928 ipp = (ip_ports *) (&p[data_ofs]);
929 sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
930 ntohs(ipp->dest));
931 break;
932 case 8:
933 strcpy(addinfo, " EGP");
934 break;
935 case 12:
936 strcpy(addinfo, " PUP");
937 break;
938 case 17:
939 ipp = (ip_ports *) (&p[data_ofs]);
940 sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
941 ntohs(ipp->dest));
942 break;
943 case 22:
944 strcpy(addinfo, " IDP");
945 break;
946 }
Harvey Harrison00bcd522008-11-13 22:41:29 -0800947 printk(KERN_INFO "OPEN: %pI4 -> %pI4%s\n",
948 p + 12, p + 16, addinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 break;
950 case ETH_P_ARP:
Harvey Harrison00bcd522008-11-13 22:41:29 -0800951 printk(KERN_INFO "OPEN: ARP %pI4 -> *.*.*.* ?%pI4\n",
952 p + 14, p + 24);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 break;
954 }
955}
956
957/*
958 * this function is used to send supervisory data, i.e. data which was
959 * not received from the network layer, but e.g. frames from ipppd, CCP
960 * reset frames etc.
961 */
962void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
963{
964 if (in_irq()) {
965 // we can't grab the lock from irq context,
966 // so we just queue the packet
967 skb_queue_tail(&lp->super_tx_queue, skb);
968 schedule_work(&lp->tqueue);
969 return;
970 }
971
972 spin_lock_bh(&lp->xmit_lock);
973 if (!isdn_net_lp_busy(lp)) {
974 isdn_net_writebuf_skb(lp, skb);
975 } else {
976 skb_queue_tail(&lp->super_tx_queue, skb);
977 }
978 spin_unlock_bh(&lp->xmit_lock);
979}
980
981/*
982 * called from tq_immediate
983 */
David Howellsc4028952006-11-22 14:57:56 +0000984static void isdn_net_softint(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
David Howellsc4028952006-11-22 14:57:56 +0000986 isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 struct sk_buff *skb;
988
989 spin_lock_bh(&lp->xmit_lock);
990 while (!isdn_net_lp_busy(lp)) {
991 skb = skb_dequeue(&lp->super_tx_queue);
992 if (!skb)
993 break;
994 isdn_net_writebuf_skb(lp, skb);
995 }
996 spin_unlock_bh(&lp->xmit_lock);
997}
998
999/*
1000 * all frames sent from the (net) LL to a HL driver should go via this function
1001 * it's serialized by the caller holding the lp->xmit_lock spinlock
1002 */
1003void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
1004{
1005 int ret;
1006 int len = skb->len; /* save len */
1007
1008 /* before obtaining the lock the caller should have checked that
1009 the lp isn't busy */
1010 if (isdn_net_lp_busy(lp)) {
1011 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1012 goto error;
1013 }
1014
1015 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1016 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1017 goto error;
1018 }
1019 ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
1020 if (ret != len) {
1021 /* we should never get here */
Karsten Keilfaca94f2007-10-15 02:11:44 -07001022 printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 goto error;
1024 }
1025
1026 lp->transcount += len;
1027 isdn_net_inc_frame_cnt(lp);
1028 return;
1029
1030 error:
1031 dev_kfree_skb(skb);
1032 lp->stats.tx_errors++;
1033
1034}
1035
1036
1037/*
1038 * Helper function for isdn_net_start_xmit.
1039 * When called, the connection is already established.
1040 * Based on cps-calculation, check if device is overloaded.
1041 * If so, and if a slave exists, trigger dialing for it.
1042 * If any slave is online, deliver packets using a simple round robin
1043 * scheme.
1044 *
1045 * Return: 0 on success, !0 on failure.
1046 */
1047
1048static int
1049isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
1050{
1051 isdn_net_dev *nd;
1052 isdn_net_local *slp;
Wang Chen838361f2008-12-03 15:49:46 -08001053 isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 int retv = 0;
1055
Wang Chen838361f2008-12-03 15:49:46 -08001056 if (((isdn_net_local *) netdev_priv(ndev))->master) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1058 dev_kfree_skb(skb);
1059 return 0;
1060 }
1061
1062 /* For the other encaps the header has already been built */
1063#ifdef CONFIG_ISDN_PPP
1064 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1065 return isdn_ppp_xmit(skb, ndev);
1066 }
1067#endif
Wang Chen838361f2008-12-03 15:49:46 -08001068 nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 lp = isdn_net_get_locked_lp(nd);
1070 if (!lp) {
1071 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
1072 return 1;
1073 }
1074 /* we have our lp locked from now on */
1075
1076 /* Reset hangup-timeout */
1077 lp->huptimer = 0; // FIXME?
1078 isdn_net_writebuf_skb(lp, skb);
1079 spin_unlock_bh(&lp->xmit_lock);
1080
1081 /* the following stuff is here for backwards compatibility.
1082 * in future, start-up and hangup of slaves (based on current load)
1083 * should move to userspace and get based on an overall cps
1084 * calculation
1085 */
1086 if (lp->cps > lp->triggercps) {
1087 if (lp->slave) {
1088 if (!lp->sqfull) {
1089 /* First time overload: set timestamp only */
1090 lp->sqfull = 1;
1091 lp->sqfull_stamp = jiffies;
1092 } else {
1093 /* subsequent overload: if slavedelay exceeded, start dialing */
1094 if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
Wang Chen838361f2008-12-03 15:49:46 -08001095 slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 if (!(slp->flags & ISDN_NET_CONNECTED)) {
Wang Chen838361f2008-12-03 15:49:46 -08001097 isdn_net_force_dial_lp(ISDN_SLAVE_PRIV(lp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 }
1099 }
1100 }
1101 }
1102 } else {
1103 if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
1104 lp->sqfull = 0;
1105 }
1106 /* this is a hack to allow auto-hangup for slaves on moderate loads */
1107 nd->queue = nd->local;
1108 }
1109
1110 return retv;
1111
1112}
1113
1114static void
1115isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
1116{
Wang Chen838361f2008-12-03 15:49:46 -08001117 isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 if (!skb)
1119 return;
1120 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001121 const int pullsize = skb_network_offset(skb) - ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 if (pullsize > 0) {
1123 printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
1124 skb_pull(skb, pullsize);
1125 }
1126 }
1127}
1128
1129
Adrian Bunk3e206b02005-06-25 14:58:35 -07001130static void isdn_net_tx_timeout(struct net_device * ndev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
Wang Chen838361f2008-12-03 15:49:46 -08001132 isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133
1134 printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
1135 if (!lp->dialstate){
1136 lp->stats.tx_errors++;
1137 /*
1138 * There is a certain probability that this currently
1139 * works at all because if we always wake up the interface,
1140 * then upper layer will try to send the next packet
1141 * immediately. And then, the old clean_up logic in the
1142 * driver will hopefully continue to work as it used to do.
1143 *
1144 * This is rather primitive right know, we better should
1145 * clean internal queues here, in particular for multilink and
1146 * ppp, and reset HL driver's channel, too. --HE
1147 *
1148 * actually, this may not matter at all, because ISDN hardware
1149 * should not see transmitter hangs at all IMO
1150 * changed KERN_DEBUG to KERN_WARNING to find out if this is
1151 * ever called --KG
1152 */
1153 }
1154 ndev->trans_start = jiffies;
1155 netif_wake_queue(ndev);
1156}
1157
1158/*
1159 * Try sending a packet.
1160 * If this interface isn't connected to a ISDN-Channel, find a free channel,
1161 * and start dialing.
1162 */
1163static int
1164isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1165{
Wang Chen838361f2008-12-03 15:49:46 -08001166 isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167#ifdef CONFIG_ISDN_X25
1168 struct concap_proto * cprot = lp -> netdev -> cprot;
1169/* At this point hard_start_xmit() passes control to the encapsulation
1170 protocol (if present).
1171 For X.25 auto-dialing is completly bypassed because:
1172 - It does not conform with the semantics of a reliable datalink
1173 service as needed by X.25 PLP.
1174 - I don't want that the interface starts dialing when the network layer
1175 sends a message which requests to disconnect the lapb link (or if it
1176 sends any other message not resulting in data transmission).
1177 Instead, dialing will be initiated by the encapsulation protocol entity
1178 when a dl_establish request is received from the upper layer.
1179*/
1180 if (cprot && cprot -> pops) {
1181 int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
1182
1183 if (ret)
1184 netif_stop_queue(ndev);
1185 return ret;
1186 } else
1187#endif
1188 /* auto-dialing xmit function */
1189 {
1190#ifdef ISDN_DEBUG_NET_DUMP
1191 u_char *buf;
1192#endif
1193 isdn_net_adjust_hdr(skb, ndev);
1194#ifdef ISDN_DEBUG_NET_DUMP
1195 buf = skb->data;
1196 isdn_dumppkt("S:", buf, skb->len, 40);
1197#endif
1198
1199 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1200 int chi;
1201 /* only do autodial if allowed by config */
1202 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
1203 isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
1204 dev_kfree_skb(skb);
1205 return 0;
1206 }
1207 if (lp->phone[1]) {
1208 ulong flags;
1209
1210 if(lp->dialwait_timer <= 0)
1211 if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
1212 lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
1213
1214 if(lp->dialwait_timer > 0) {
1215 if(time_before(jiffies, lp->dialwait_timer)) {
1216 isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
1217 dev_kfree_skb(skb);
1218 return 0;
1219 } else
1220 lp->dialwait_timer = 0;
1221 }
1222 /* Grab a free ISDN-Channel */
1223 spin_lock_irqsave(&dev->lock, flags);
1224 if (((chi =
1225 isdn_get_free_channel(
1226 ISDN_USAGE_NET,
1227 lp->l2_proto,
1228 lp->l3_proto,
1229 lp->pre_device,
1230 lp->pre_channel,
1231 lp->msn)
1232 ) < 0) &&
1233 ((chi =
1234 isdn_get_free_channel(
1235 ISDN_USAGE_NET,
1236 lp->l2_proto,
1237 lp->l3_proto,
1238 lp->pre_device,
1239 lp->pre_channel^1,
1240 lp->msn)
1241 ) < 0)) {
1242 spin_unlock_irqrestore(&dev->lock, flags);
1243 isdn_net_unreachable(ndev, skb,
1244 "No channel");
1245 dev_kfree_skb(skb);
1246 return 0;
1247 }
1248 /* Log packet, which triggered dialing */
1249 if (dev->net_verbose)
1250 isdn_net_log_skb(skb, lp);
1251 lp->dialstate = 1;
1252 /* Connect interface with channel */
1253 isdn_net_bind_channel(lp, chi);
1254#ifdef CONFIG_ISDN_PPP
1255 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1256 /* no 'first_skb' handling for syncPPP */
1257 if (isdn_ppp_bind(lp) < 0) {
1258 dev_kfree_skb(skb);
1259 isdn_net_unbind_channel(lp);
1260 spin_unlock_irqrestore(&dev->lock, flags);
1261 return 0; /* STN (skb to nirvana) ;) */
1262 }
1263#ifdef CONFIG_IPPP_FILTER
1264 if (isdn_ppp_autodial_filter(skb, lp)) {
1265 isdn_ppp_free(lp);
1266 isdn_net_unbind_channel(lp);
1267 spin_unlock_irqrestore(&dev->lock, flags);
1268 isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
1269 dev_kfree_skb(skb);
1270 return 0;
1271 }
1272#endif
1273 spin_unlock_irqrestore(&dev->lock, flags);
1274 isdn_net_dial(); /* Initiate dialing */
1275 netif_stop_queue(ndev);
1276 return 1; /* let upper layer requeue skb packet */
1277 }
1278#endif
1279 /* Initiate dialing */
1280 spin_unlock_irqrestore(&dev->lock, flags);
1281 isdn_net_dial();
1282 isdn_net_device_stop_queue(lp);
1283 return 1;
1284 } else {
1285 isdn_net_unreachable(ndev, skb,
1286 "No phone number");
1287 dev_kfree_skb(skb);
1288 return 0;
1289 }
1290 } else {
1291 /* Device is connected to an ISDN channel */
1292 ndev->trans_start = jiffies;
1293 if (!lp->dialstate) {
1294 /* ISDN connection is established, try sending */
1295 int ret;
1296 ret = (isdn_net_xmit(ndev, skb));
1297 if(ret) netif_stop_queue(ndev);
1298 return ret;
1299 } else
1300 netif_stop_queue(ndev);
1301 }
1302 }
1303 return 1;
1304}
1305
1306/*
1307 * Shutdown a net-interface.
1308 */
1309static int
1310isdn_net_close(struct net_device *dev)
1311{
1312 struct net_device *p;
1313#ifdef CONFIG_ISDN_X25
1314 struct concap_proto * cprot =
Wang Chen838361f2008-12-03 15:49:46 -08001315 ((isdn_net_local *) netdev_priv(dev))->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
1317#endif
1318
1319#ifdef CONFIG_ISDN_X25
1320 if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
1321#endif
1322 netif_stop_queue(dev);
Wang Chen838361f2008-12-03 15:49:46 -08001323 p = MASTER_TO_SLAVE(dev);
1324 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 /* If this interface has slaves, stop them also */
1326 while (p) {
1327#ifdef CONFIG_ISDN_X25
Wang Chen838361f2008-12-03 15:49:46 -08001328 cprot = ((isdn_net_local *) netdev_priv(p))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 -> netdev -> cprot;
1330 if( cprot && cprot -> pops )
1331 cprot -> pops -> close( cprot );
1332#endif
1333 isdn_net_hangup(p);
Wang Chen838361f2008-12-03 15:49:46 -08001334 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 }
1336 }
1337 isdn_net_hangup(dev);
1338 isdn_unlock_drivers();
1339 return 0;
1340}
1341
1342/*
1343 * Get statistics
1344 */
1345static struct net_device_stats *
1346isdn_net_get_stats(struct net_device *dev)
1347{
Wang Chen838361f2008-12-03 15:49:46 -08001348 isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return &lp->stats;
1350}
1351
1352/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
1353 * instead of dev->hard_header_len off. This is done because the
1354 * lowlevel-driver has already pulled off its stuff when we get
1355 * here and this routine only gets called with p_encap == ETHER.
1356 * Determine the packet's protocol ID. The rule here is that we
1357 * assume 802.3 if the type field is short enough to be a length.
1358 * This is normal practice and works for any 'now in use' protocol.
1359 */
1360
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001361static __be16
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
1363{
1364 struct ethhdr *eth;
1365 unsigned char *rawp;
1366
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -07001367 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 skb_pull(skb, ETH_HLEN);
1369 eth = eth_hdr(skb);
1370
1371 if (*eth->h_dest & 1) {
1372 if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
1373 skb->pkt_type = PACKET_BROADCAST;
1374 else
1375 skb->pkt_type = PACKET_MULTICAST;
1376 }
1377 /*
1378 * This ALLMULTI check should be redundant by 1.4
1379 * so don't forget to remove it.
1380 */
1381
1382 else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
1383 if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
1384 skb->pkt_type = PACKET_OTHERHOST;
1385 }
1386 if (ntohs(eth->h_proto) >= 1536)
1387 return eth->h_proto;
1388
1389 rawp = skb->data;
1390
1391 /*
1392 * This is a magic hack to spot IPX packets. Older Novell breaks
1393 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
1394 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
1395 * won't work for fault tolerant netware but does for the rest.
1396 */
1397 if (*(unsigned short *) rawp == 0xFFFF)
1398 return htons(ETH_P_802_3);
1399 /*
1400 * Real 802.2 LLC
1401 */
1402 return htons(ETH_P_802_2);
1403}
1404
1405
1406/*
1407 * CISCO HDLC keepalive specific stuff
1408 */
1409static struct sk_buff*
1410isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
1411{
1412 unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
1413 struct sk_buff *skb;
1414
1415 skb = alloc_skb(hl + len, GFP_ATOMIC);
1416 if (skb)
1417 skb_reserve(skb, hl);
1418 else
1419 printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
1420 return skb;
1421}
1422
1423/* cisco hdlck device private ioctls */
Adrian Bunk3e206b02005-06-25 14:58:35 -07001424static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1426{
Wang Chen838361f2008-12-03 15:49:46 -08001427 isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 unsigned long len = 0;
1429 unsigned long expires = 0;
1430 int tmp = 0;
1431 int period = lp->cisco_keepalive_period;
1432 s8 debserint = lp->cisco_debserint;
1433 int rc = 0;
1434
1435 if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
1436 return -EINVAL;
1437
1438 switch (cmd) {
1439 /* get/set keepalive period */
1440 case SIOCGKEEPPERIOD:
1441 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1442 if (copy_to_user(ifr->ifr_data,
1443 &lp->cisco_keepalive_period, len))
1444 rc = -EFAULT;
1445 break;
1446 case SIOCSKEEPPERIOD:
1447 tmp = lp->cisco_keepalive_period;
1448 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1449 if (copy_from_user(&period, ifr->ifr_data, len))
1450 rc = -EFAULT;
1451 if ((period > 0) && (period <= 32767))
1452 lp->cisco_keepalive_period = period;
1453 else
1454 rc = -EINVAL;
1455 if (!rc && (tmp != lp->cisco_keepalive_period)) {
1456 expires = (unsigned long)(jiffies +
1457 lp->cisco_keepalive_period * HZ);
1458 mod_timer(&lp->cisco_timer, expires);
1459 printk(KERN_INFO "%s: Keepalive period set "
1460 "to %d seconds.\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001461 dev->name, lp->cisco_keepalive_period);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 }
1463 break;
1464
1465 /* get/set debugging */
1466 case SIOCGDEBSERINT:
1467 len = (unsigned long)sizeof(lp->cisco_debserint);
1468 if (copy_to_user(ifr->ifr_data,
1469 &lp->cisco_debserint, len))
1470 rc = -EFAULT;
1471 break;
1472 case SIOCSDEBSERINT:
1473 len = (unsigned long)sizeof(lp->cisco_debserint);
1474 if (copy_from_user(&debserint,
1475 ifr->ifr_data, len))
1476 rc = -EFAULT;
1477 if ((debserint >= 0) && (debserint <= 64))
1478 lp->cisco_debserint = debserint;
1479 else
1480 rc = -EINVAL;
1481 break;
1482
1483 default:
1484 rc = -EINVAL;
1485 break;
1486 }
1487 return (rc);
1488}
1489
Stephen Hemmingerd7005552009-01-07 18:04:17 -08001490
1491static int isdn_net_ioctl(struct net_device *dev,
1492 struct ifreq *ifr, int cmd)
1493{
1494 isdn_net_local *lp = (isdn_net_local *) netdev_priv(dev);
1495
1496 switch (lp->p_encap) {
1497#ifdef CONFIG_ISDN_PPP
1498 case ISDN_NET_ENCAP_SYNCPPP:
1499 return isdn_ppp_dev_ioctl(dev, ifr, cmd);
1500#endif
1501 case ISDN_NET_ENCAP_CISCOHDLCK:
1502 return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
1503 default:
1504 return -EINVAL;
1505 }
1506}
1507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508/* called via cisco_timer.function */
1509static void
1510isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
1511{
1512 isdn_net_local *lp = (isdn_net_local *) data;
1513 struct sk_buff *skb;
1514 unsigned char *p;
1515 unsigned long last_cisco_myseq = lp->cisco_myseq;
1516 int myseq_diff = 0;
1517
1518 if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
1519 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1520 return;
1521 }
1522 lp->cisco_myseq++;
1523
1524 myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
1525 if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) {
1526 /* line up -> down */
1527 lp->cisco_line_state = 0;
1528 printk (KERN_WARNING
1529 "UPDOWN: Line protocol on Interface %s,"
Karsten Keilfaca94f2007-10-15 02:11:44 -07001530 " changed state to down\n", lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 /* should stop routing higher-level data accross */
1532 } else if ((!lp->cisco_line_state) &&
1533 (myseq_diff >= 0) && (myseq_diff <= 2)) {
1534 /* line down -> up */
1535 lp->cisco_line_state = 1;
1536 printk (KERN_WARNING
1537 "UPDOWN: Line protocol on Interface %s,"
Karsten Keilfaca94f2007-10-15 02:11:44 -07001538 " changed state to up\n", lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 /* restart routing higher-level data accross */
1540 }
1541
1542 if (lp->cisco_debserint)
1543 printk (KERN_DEBUG "%s: HDLC "
1544 "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001545 lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
1547 lp->cisco_yourseq,
1548 ((lp->cisco_line_state) ? "line up" : "line down"));
1549
1550 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1551 if (!skb)
1552 return;
1553
1554 p = skb_put(skb, 4 + 14);
1555
1556 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001557 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1558 *(u8 *)(p + 1) = CISCO_CTRL;
1559 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
1561 /* slarp keepalive */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001562 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE);
1563 *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq);
1564 *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq);
1565 *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliablity, always 0xffff
1566 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 isdn_net_write_super(lp, skb);
1569
1570 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1571
1572 add_timer(&lp->cisco_timer);
1573}
1574
1575static void
1576isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
1577{
1578 struct sk_buff *skb;
1579 unsigned char *p;
1580
1581 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1582 if (!skb)
1583 return;
1584
1585 p = skb_put(skb, 4 + 14);
1586
1587 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001588 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1589 *(u8 *)(p + 1) = CISCO_CTRL;
1590 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 /* slarp request */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001593 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REQUEST);
1594 *(__be32 *)(p + 8) = cpu_to_be32(0); // address
1595 *(__be32 *)(p + 12) = cpu_to_be32(0); // netmask
1596 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1597 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 isdn_net_write_super(lp, skb);
1600}
1601
1602static void
1603isdn_net_ciscohdlck_connected(isdn_net_local *lp)
1604{
1605 lp->cisco_myseq = 0;
1606 lp->cisco_mineseen = 0;
1607 lp->cisco_yourseq = 0;
1608 lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
1609 lp->cisco_last_slarp_in = 0;
1610 lp->cisco_line_state = 0;
1611 lp->cisco_debserint = 0;
1612
1613 /* send slarp request because interface/seq.no.s reset */
1614 isdn_net_ciscohdlck_slarp_send_request(lp);
1615
1616 init_timer(&lp->cisco_timer);
1617 lp->cisco_timer.data = (unsigned long) lp;
1618 lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
1619 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1620 add_timer(&lp->cisco_timer);
1621}
1622
1623static void
1624isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
1625{
1626 del_timer(&lp->cisco_timer);
1627}
1628
1629static void
1630isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
1631{
1632 struct sk_buff *skb;
1633 unsigned char *p;
1634 struct in_device *in_dev = NULL;
Al Viroa144ea42006-09-28 18:00:55 -07001635 __be32 addr = 0; /* local ipv4 address */
1636 __be32 mask = 0; /* local netmask */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
Karsten Keild62a38d2007-10-08 20:37:11 -07001638 if ((in_dev = lp->netdev->dev->ip_ptr) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 /* take primary(first) address of interface */
1640 struct in_ifaddr *ifa = in_dev->ifa_list;
1641 if (ifa != NULL) {
1642 addr = ifa->ifa_local;
1643 mask = ifa->ifa_mask;
1644 }
1645 }
1646
1647 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1648 if (!skb)
1649 return;
1650
1651 p = skb_put(skb, 4 + 14);
1652
1653 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001654 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1655 *(u8 *)(p + 1) = CISCO_CTRL;
1656 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 /* slarp reply, send own ip/netmask; if values are nonsense remote
1659 * should think we are unable to provide it with an address via SLARP */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001660 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REPLY);
David S. Miller198d6ba2008-11-18 23:38:23 -08001661 *(__be32 *)(p + 8) = addr; // address
1662 *(__be32 *)(p + 12) = mask; // netmask
Harvey Harrison00bcd522008-11-13 22:41:29 -08001663 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1664 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 isdn_net_write_super(lp, skb);
1667}
1668
1669static void
1670isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
1671{
1672 unsigned char *p;
1673 int period;
1674 u32 code;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001675 u32 my_seq;
1676 u32 your_seq;
1677 __be32 local;
1678 __be32 *addr, *mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 u16 unused;
1680
1681 if (skb->len < 14)
1682 return;
1683
1684 p = skb->data;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001685 code = be32_to_cpup((__be32 *)p);
1686 p += 4;
1687
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 switch (code) {
1689 case CISCO_SLARP_REQUEST:
1690 lp->cisco_yourseq = 0;
1691 isdn_net_ciscohdlck_slarp_send_reply(lp);
1692 break;
1693 case CISCO_SLARP_REPLY:
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001694 addr = (__be32 *)p;
1695 mask = (__be32 *)(p + 4);
1696 if (*mask != cpu_to_be32(0xfffffffc))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 goto slarp_reply_out;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001698 if ((*addr & cpu_to_be32(3)) == cpu_to_be32(0) ||
1699 (*addr & cpu_to_be32(3)) == cpu_to_be32(3))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 goto slarp_reply_out;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001701 local = *addr ^ cpu_to_be32(3);
1702 printk(KERN_INFO "%s: got slarp reply: remote ip: %pI4, local ip: %pI4 mask: %pI4\n",
1703 lp->netdev->dev->name, addr, &local, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 break;
1705 slarp_reply_out:
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001706 printk(KERN_INFO "%s: got invalid slarp reply (%pI4/%pI4) - ignored\n",
1707 lp->netdev->dev->name, addr, mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 break;
1709 case CISCO_SLARP_KEEPALIVE:
1710 period = (int)((jiffies - lp->cisco_last_slarp_in
1711 + HZ/2 - 1) / HZ);
1712 if (lp->cisco_debserint &&
1713 (period != lp->cisco_keepalive_period) &&
1714 lp->cisco_last_slarp_in) {
1715 printk(KERN_DEBUG "%s: Keepalive period mismatch - "
1716 "is %d but should be %d.\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001717 lp->netdev->dev->name, period,
1718 lp->cisco_keepalive_period);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719 }
1720 lp->cisco_last_slarp_in = jiffies;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001721 my_seq = be32_to_cpup((__be32 *)(p + 0));
1722 your_seq = be32_to_cpup((__be32 *)(p + 4));
1723 unused = be16_to_cpup((__be16 *)(p + 8));
1724 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;
1735 u8 addr;
1736 u8 ctrl;
1737 u16 type;
1738
1739 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);
1748
1749 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 "
Karsten Keilfaca94f2007-10-15 02:11:44 -07001767 "\"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
1777 out_free:
1778 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{
Wang Chen838361f2008-12-03 15:49:46 -08001787 isdn_net_local *lp = (isdn_net_local *) netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 isdn_net_local *olp = lp; /* original 'lp' */
1789#ifdef CONFIG_ISDN_X25
1790 struct concap_proto *cprot = lp -> netdev -> cprot;
1791#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;
Wang Chen838361f2008-12-03 15:49:46 -08001801 lp = (isdn_net_local *) 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) {
1812 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;
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001841 skb->protocol = *(__be16 *)&(skb->data[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 skb_pull(skb, 2);
1843 if (*(unsigned short *) skb->data == 0xFFFF)
1844 skb->protocol = htons(ETH_P_802_3);
1845 break;
1846#ifdef CONFIG_ISDN_PPP
1847 case ISDN_NET_ENCAP_SYNCPPP:
1848 /* huptimer is done in isdn_ppp_push_higher */
1849 isdn_ppp_receive(lp->netdev, olp, skb);
1850 return;
1851#endif
1852
1853 default:
1854#ifdef CONFIG_ISDN_X25
1855 /* 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 };
1861#endif /* CONFIG_ISDN_X25 */
1862 printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001863 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 kfree_skb(skb);
1865 return;
1866 }
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;
1904 ushort len = 0;
1905
1906 switch (lp->p_encap) {
1907 case ISDN_NET_ENCAP_ETHER:
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001908 len = eth_header(skb, dev, type, daddr, saddr, plen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909 break;
1910#ifdef CONFIG_ISDN_PPP
1911 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;
1916#endif
1917 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 */
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001923 *((__be16 *)skb_push(skb, 2)) = htons(type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 len = 2;
1925 break;
1926 case ISDN_NET_ENCAP_UIHDLC:
1927 /* HDLC with UI-Frames (for ispa with -h1 option) */
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001928 *((__be16 *)skb_push(skb, 2)) = htons(0x0103);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 len = 2;
1930 break;
1931 case ISDN_NET_ENCAP_CISCOHDLC:
1932 case ISDN_NET_ENCAP_CISCOHDLCK:
1933 p = skb_push(skb, 4);
Harvey Harrison00bcd522008-11-13 22:41:29 -08001934 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1935 *(u8 *)(p + 1) = CISCO_CTRL;
1936 *(__be16 *)(p + 2) = cpu_to_be16(type);
1937 p += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 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");
1945 len = 0;
1946 break;
1947 }
1948 break;
1949#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
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001986static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh)
1987{
1988 const struct net_device *dev = neigh->dev;
Wang Chen838361f2008-12-03 15:49:46 -08001989 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001990
1991 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
1992 return eth_header_cache(neigh, hh);
1993 return -1;
1994}
1995
1996static void isdn_header_cache_update(struct hh_cache *hh,
1997 const struct net_device *dev,
1998 const unsigned char *haddr)
1999{
Wang Chen838361f2008-12-03 15:49:46 -08002000 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002001 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
Harvey Harrisonc19d0362008-11-20 04:10:51 -08002002 eth_header_cache_update(hh, dev, haddr);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002003}
2004
2005static const struct header_ops isdn_header_ops = {
2006 .create = isdn_net_header,
2007 .rebuild = isdn_net_rebuild_header,
2008 .cache = isdn_header_cache,
2009 .cache_update = isdn_header_cache_update,
2010};
2011
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012/*
2013 * Interface-setup. (just after registering a new interface)
2014 */
2015static int
2016isdn_net_init(struct net_device *ndev)
2017{
2018 ushort max_hlhdr_len = 0;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002019 int drvidx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 /*
2022 * up till binding we ask the protocol layer to reserve as much
2023 * as we might need for HL layer
2024 */
2025
2026 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2027 if (dev->drv[drvidx])
2028 if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
2029 max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
2030
2031 ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032 return 0;
2033}
2034
2035static void
2036isdn_net_swapbind(int drvidx)
2037{
2038 isdn_net_dev *p;
2039
2040#ifdef ISDN_DEBUG_NET_ICALL
2041 printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
2042#endif
2043 p = dev->netdev;
2044 while (p) {
2045 if (p->local->pre_device == drvidx)
2046 switch (p->local->pre_channel) {
2047 case 0:
2048 p->local->pre_channel = 1;
2049 break;
2050 case 1:
2051 p->local->pre_channel = 0;
2052 break;
2053 }
2054 p = (isdn_net_dev *) p->next;
2055 }
2056}
2057
2058static void
2059isdn_net_swap_usage(int i1, int i2)
2060{
2061 int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
2062 int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
2063
2064#ifdef ISDN_DEBUG_NET_ICALL
2065 printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
2066#endif
2067 dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
2068 dev->usage[i1] |= u2;
2069 dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
2070 dev->usage[i2] |= u1;
2071 isdn_info_update();
2072}
2073
2074/*
2075 * An incoming call-request has arrived.
2076 * Search the interface-chain for an appropriate interface.
2077 * If found, connect the interface to the ISDN-channel and initiate
2078 * D- and B-Channel-setup. If secure-flag is set, accept only
2079 * configured phone-numbers. If callback-flag is set, initiate
2080 * callback-dialing.
2081 *
2082 * Return-Value: 0 = No appropriate interface for this call.
2083 * 1 = Call accepted
2084 * 2 = Reject call, wait cbdelay, then call back
2085 * 3 = Reject call
2086 * 4 = Wait cbdelay, then call back
2087 * 5 = No appropriate interface for this call,
2088 * would eventually match if CID was longer.
2089 */
2090
2091int
2092isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
2093{
2094 char *eaz;
2095 int si1;
2096 int si2;
2097 int ematch;
2098 int wret;
2099 int swapped;
2100 int sidx = 0;
2101 u_long flags;
2102 isdn_net_dev *p;
2103 isdn_net_phone *n;
Karsten Keil0f138642007-11-22 12:43:13 +01002104 char nr[ISDN_MSNLEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 char *my_eaz;
2106
2107 /* Search name in netdev-chain */
2108 if (!setup->phone[0]) {
2109 nr[0] = '0';
2110 nr[1] = '\0';
2111 printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
2112 } else
Karsten Keil0f138642007-11-22 12:43:13 +01002113 strlcpy(nr, setup->phone, ISDN_MSNLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114 si1 = (int) setup->si1;
2115 si2 = (int) setup->si2;
2116 if (!setup->eazmsn[0]) {
2117 printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
2118 eaz = "0";
2119 } else
2120 eaz = setup->eazmsn;
2121 if (dev->net_verbose > 1)
2122 printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
2123 /* Accept DATA and VOICE calls at this stage
2124 * local eaz is checked later for allowed call types
2125 */
2126 if ((si1 != 7) && (si1 != 1)) {
2127 if (dev->net_verbose > 1)
2128 printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
2129 return 0;
2130 }
2131 n = (isdn_net_phone *) 0;
2132 p = dev->netdev;
2133 ematch = wret = swapped = 0;
2134#ifdef ISDN_DEBUG_NET_ICALL
2135 printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
2136 dev->usage[idx]);
2137#endif
2138 while (p) {
2139 int matchret;
2140 isdn_net_local *lp = p->local;
2141
2142 /* If last check has triggered as binding-swap, revert it */
2143 switch (swapped) {
2144 case 2:
2145 isdn_net_swap_usage(idx, sidx);
2146 /* fall through */
2147 case 1:
2148 isdn_net_swapbind(di);
2149 break;
2150 }
2151 swapped = 0;
2152 /* check acceptable call types for DOV */
2153 my_eaz = isdn_map_eaz2msn(lp->msn, di);
2154 if (si1 == 1) { /* it's a DOV call, check if we allow it */
2155 if (*my_eaz == 'v' || *my_eaz == 'V' ||
2156 *my_eaz == 'b' || *my_eaz == 'B')
2157 my_eaz++; /* skip to allow a match */
2158 else
2159 my_eaz = NULL; /* force non match */
2160 } else { /* it's a DATA call, check if we allow it */
2161 if (*my_eaz == 'b' || *my_eaz == 'B')
2162 my_eaz++; /* skip to allow a match */
2163 }
2164 if (my_eaz)
2165 matchret = isdn_msncmp(eaz, my_eaz);
2166 else
2167 matchret = 1;
2168 if (!matchret)
2169 ematch = 1;
2170
2171 /* Remember if more numbers eventually can match */
2172 if (matchret > wret)
2173 wret = matchret;
2174#ifdef ISDN_DEBUG_NET_ICALL
2175 printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002176 p->dev->name, lp->msn, lp->flags, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177#endif
2178 if ((!matchret) && /* EAZ is matching */
2179 (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
2180 (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
2181 ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
2182 (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
2183 )))
2184 {
2185#ifdef ISDN_DEBUG_NET_ICALL
2186 printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
2187 lp->pre_device, lp->pre_channel);
2188#endif
2189 if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
2190 if ((lp->pre_channel != ch) ||
2191 (lp->pre_device != di)) {
2192 /* Here we got a problem:
2193 * If using an ICN-Card, an incoming call is always signaled on
2194 * on the first channel of the card, if both channels are
2195 * down. However this channel may be bound exclusive. If the
2196 * second channel is free, this call should be accepted.
2197 * The solution is horribly but it runs, so what:
2198 * We exchange the exclusive bindings of the two channels, the
2199 * corresponding variables in the interface-structs.
2200 */
2201 if (ch == 0) {
2202 sidx = isdn_dc2minor(di, 1);
2203#ifdef ISDN_DEBUG_NET_ICALL
2204 printk(KERN_DEBUG "n_fi: ch is 0\n");
2205#endif
2206 if (USG_NONE(dev->usage[sidx])) {
2207 /* Second Channel is free, now see if it is bound
2208 * exclusive too. */
2209 if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
2210#ifdef ISDN_DEBUG_NET_ICALL
2211 printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
2212#endif
2213 /* Yes, swap bindings only, if the original
2214 * binding is bound to channel 1 of this driver */
2215 if ((lp->pre_device == di) &&
2216 (lp->pre_channel == 1)) {
2217 isdn_net_swapbind(di);
2218 swapped = 1;
2219 } else {
2220 /* ... else iterate next device */
2221 p = (isdn_net_dev *) p->next;
2222 continue;
2223 }
2224 } else {
2225#ifdef ISDN_DEBUG_NET_ICALL
2226 printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
2227#endif
2228 /* No, swap always and swap excl-usage also */
2229 isdn_net_swap_usage(idx, sidx);
2230 isdn_net_swapbind(di);
2231 swapped = 2;
2232 }
2233 /* Now check for exclusive binding again */
2234#ifdef ISDN_DEBUG_NET_ICALL
2235 printk(KERN_DEBUG "n_fi: final check\n");
2236#endif
2237 if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
2238 ((lp->pre_channel != ch) ||
2239 (lp->pre_device != di))) {
2240#ifdef ISDN_DEBUG_NET_ICALL
2241 printk(KERN_DEBUG "n_fi: final check failed\n");
2242#endif
2243 p = (isdn_net_dev *) p->next;
2244 continue;
2245 }
2246 }
2247 } else {
2248 /* We are already on the second channel, so nothing to do */
2249#ifdef ISDN_DEBUG_NET_ICALL
2250 printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
2251#endif
2252 }
2253 }
2254 }
2255#ifdef ISDN_DEBUG_NET_ICALL
2256 printk(KERN_DEBUG "n_fi: match2\n");
2257#endif
2258 n = lp->phone[0];
2259 if (lp->flags & ISDN_NET_SECURE) {
2260 while (n) {
2261 if (!isdn_msncmp(nr, n->num))
2262 break;
2263 n = (isdn_net_phone *) n->next;
2264 }
2265 }
2266 if (n || (!(lp->flags & ISDN_NET_SECURE))) {
2267#ifdef ISDN_DEBUG_NET_ICALL
2268 printk(KERN_DEBUG "n_fi: match3\n");
2269#endif
2270 /* matching interface found */
2271
2272 /*
2273 * Is the state STOPPED?
2274 * If so, no dialin is allowed,
2275 * so reject actively.
2276 * */
2277 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2278 printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002279 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 return 3;
2281 }
2282 /*
2283 * Is the interface up?
2284 * If not, reject the call actively.
2285 */
2286 if (!isdn_net_device_started(p)) {
2287 printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002288 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289 return 3;
2290 }
2291 /* Interface is up, now see if it's a slave. If so, see if
2292 * it's master and parent slave is online. If not, reject the call.
2293 */
2294 if (lp->master) {
Wang Chen838361f2008-12-03 15:49:46 -08002295 isdn_net_local *mlp = ISDN_MASTER_PRIV(lp);
Karsten Keilfaca94f2007-10-15 02:11:44 -07002296 printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
2297 printk(KERN_DEBUG "master=%s\n", lp->master->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 if (mlp->flags & ISDN_NET_CONNECTED) {
2299 printk(KERN_DEBUG "master online\n");
2300 /* Master is online, find parent-slave (master if first slave) */
2301 while (mlp->slave) {
Wang Chen838361f2008-12-03 15:49:46 -08002302 if (ISDN_SLAVE_PRIV(mlp) == lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 break;
Wang Chen838361f2008-12-03 15:49:46 -08002304 mlp = ISDN_SLAVE_PRIV(mlp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305 }
2306 } else
2307 printk(KERN_DEBUG "master offline\n");
2308 /* Found parent, if it's offline iterate next device */
2309 printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
2310 if (!(mlp->flags & ISDN_NET_CONNECTED)) {
2311 p = (isdn_net_dev *) p->next;
2312 continue;
2313 }
2314 }
2315 if (lp->flags & ISDN_NET_CALLBACK) {
2316 int chi;
2317 /*
2318 * Is the state MANUAL?
2319 * If so, no callback can be made,
2320 * so reject actively.
2321 * */
2322 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2323 printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002324 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325 return 3;
2326 }
2327 printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002328 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 if (lp->phone[1]) {
2330 /* Grab a free ISDN-Channel */
2331 spin_lock_irqsave(&dev->lock, flags);
2332 if ((chi =
2333 isdn_get_free_channel(
2334 ISDN_USAGE_NET,
2335 lp->l2_proto,
2336 lp->l3_proto,
2337 lp->pre_device,
2338 lp->pre_channel,
2339 lp->msn)
2340 ) < 0) {
2341
Karsten Keilfaca94f2007-10-15 02:11:44 -07002342 printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
2343 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 spin_unlock_irqrestore(&dev->lock, flags);
2345 return 0;
2346 }
2347 /* Setup dialstate. */
2348 lp->dtimer = 0;
2349 lp->dialstate = 11;
2350 /* Connect interface with channel */
2351 isdn_net_bind_channel(lp, chi);
2352#ifdef CONFIG_ISDN_PPP
2353 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2354 if (isdn_ppp_bind(lp) < 0) {
2355 spin_unlock_irqrestore(&dev->lock, flags);
2356 isdn_net_unbind_channel(lp);
2357 return 0;
2358 }
2359#endif
2360 spin_unlock_irqrestore(&dev->lock, flags);
2361 /* Initiate dialing by returning 2 or 4 */
2362 return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
2363 } else
Karsten Keilfaca94f2007-10-15 02:11:44 -07002364 printk(KERN_WARNING "isdn_net: %s: No phone number\n",
2365 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 return 0;
2367 } else {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002368 printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
2369 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 /* if this interface is dialing, it does it probably on a different
2371 device, so free this device */
2372 if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
2373#ifdef CONFIG_ISDN_PPP
2374 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2375 isdn_ppp_free(lp);
2376#endif
2377 isdn_net_lp_disconnected(lp);
2378 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
2379 ISDN_USAGE_NET);
2380 }
2381 spin_lock_irqsave(&dev->lock, flags);
2382 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2383 dev->usage[idx] |= ISDN_USAGE_NET;
2384 strcpy(dev->num[idx], nr);
2385 isdn_info_update();
2386 dev->st_netdev[idx] = lp->netdev;
2387 lp->isdn_device = di;
2388 lp->isdn_channel = ch;
2389 lp->ppp_slot = -1;
2390 lp->flags |= ISDN_NET_CONNECTED;
2391 lp->dialstate = 7;
2392 lp->dtimer = 0;
2393 lp->outgoing = 0;
2394 lp->huptimer = 0;
2395 lp->hupflags |= ISDN_WAITCHARGE;
2396 lp->hupflags &= ~ISDN_HAVECHARGE;
2397#ifdef CONFIG_ISDN_PPP
2398 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
2399 if (isdn_ppp_bind(lp) < 0) {
2400 isdn_net_unbind_channel(lp);
2401 spin_unlock_irqrestore(&dev->lock, flags);
2402 return 0;
2403 }
2404 }
2405#endif
2406 spin_unlock_irqrestore(&dev->lock, flags);
2407 return 1;
2408 }
2409 }
2410 }
2411 p = (isdn_net_dev *) p->next;
2412 }
2413 /* If none of configured EAZ/MSN matched and not verbose, be silent */
2414 if (!ematch || dev->net_verbose)
2415 printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
2416 return (wret == 2)?5:0;
2417}
2418
2419/*
2420 * Search list of net-interfaces for an interface with given name.
2421 */
2422isdn_net_dev *
2423isdn_net_findif(char *name)
2424{
2425 isdn_net_dev *p = dev->netdev;
2426
2427 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002428 if (!strcmp(p->dev->name, name))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 return p;
2430 p = (isdn_net_dev *) p->next;
2431 }
2432 return (isdn_net_dev *) NULL;
2433}
2434
2435/*
2436 * Force a net-interface to dial out.
2437 * This is called from the userlevel-routine below or
2438 * from isdn_net_start_xmit().
2439 */
Adrian Bunk3e206b02005-06-25 14:58:35 -07002440static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441isdn_net_force_dial_lp(isdn_net_local * lp)
2442{
2443 if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
2444 int chi;
2445 if (lp->phone[1]) {
2446 ulong flags;
2447
2448 /* Grab a free ISDN-Channel */
2449 spin_lock_irqsave(&dev->lock, flags);
2450 if ((chi = isdn_get_free_channel(
2451 ISDN_USAGE_NET,
2452 lp->l2_proto,
2453 lp->l3_proto,
2454 lp->pre_device,
2455 lp->pre_channel,
2456 lp->msn)) < 0) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002457 printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
2458 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 spin_unlock_irqrestore(&dev->lock, flags);
2460 return -EAGAIN;
2461 }
2462 lp->dialstate = 1;
2463 /* Connect interface with channel */
2464 isdn_net_bind_channel(lp, chi);
2465#ifdef CONFIG_ISDN_PPP
2466 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2467 if (isdn_ppp_bind(lp) < 0) {
2468 isdn_net_unbind_channel(lp);
2469 spin_unlock_irqrestore(&dev->lock, flags);
2470 return -EAGAIN;
2471 }
2472#endif
2473 /* Initiate dialing */
2474 spin_unlock_irqrestore(&dev->lock, flags);
2475 isdn_net_dial();
2476 return 0;
2477 } else
2478 return -EINVAL;
2479 } else
2480 return -EBUSY;
2481}
2482
2483/*
2484 * This is called from certain upper protocol layers (multilink ppp
2485 * and x25iface encapsulation module) that want to initiate dialing
2486 * themselves.
2487 */
2488int
2489isdn_net_dial_req(isdn_net_local * lp)
2490{
2491 /* is there a better error code? */
2492 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
2493
2494 return isdn_net_force_dial_lp(lp);
2495}
2496
2497/*
2498 * Force a net-interface to dial out.
2499 * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
2500 */
2501int
2502isdn_net_force_dial(char *name)
2503{
2504 isdn_net_dev *p = isdn_net_findif(name);
2505
2506 if (!p)
2507 return -ENODEV;
2508 return (isdn_net_force_dial_lp(p->local));
2509}
2510
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002511/* The ISDN-specific entries in the device structure. */
2512static const struct net_device_ops isdn_netdev_ops = {
2513 .ndo_init = isdn_net_init,
2514 .ndo_open = isdn_net_open,
2515 .ndo_stop = isdn_net_close,
2516 .ndo_do_ioctl = isdn_net_ioctl,
2517
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002518 .ndo_start_xmit = isdn_net_start_xmit,
2519 .ndo_get_stats = isdn_net_get_stats,
2520 .ndo_tx_timeout = isdn_net_tx_timeout,
2521};
2522
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523/*
Karsten Keild62a38d2007-10-08 20:37:11 -07002524 * Helper for alloc_netdev()
2525 */
2526static void _isdn_setup(struct net_device *dev)
2527{
Wang Chen838361f2008-12-03 15:49:46 -08002528 isdn_net_local *lp = netdev_priv(dev);
Karsten Keild62a38d2007-10-08 20:37:11 -07002529
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002530 ether_setup(dev);
2531
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002532 /* Setup the generic properties */
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002533 dev->flags = IFF_NOARP|IFF_POINTOPOINT;
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002534 dev->header_ops = NULL;
2535 dev->netdev_ops = &isdn_netdev_ops;
2536
2537 /* for clients with MPPP maybe higher values better */
2538 dev->tx_queue_len = 30;
2539
Karsten Keild62a38d2007-10-08 20:37:11 -07002540 lp->p_encap = ISDN_NET_ENCAP_RAWIP;
2541 lp->magic = ISDN_NET_MAGIC;
2542 lp->last = lp;
2543 lp->next = lp;
2544 lp->isdn_device = -1;
2545 lp->isdn_channel = -1;
2546 lp->pre_device = -1;
2547 lp->pre_channel = -1;
2548 lp->exclusive = -1;
2549 lp->ppp_slot = -1;
2550 lp->pppbind = -1;
2551 skb_queue_head_init(&lp->super_tx_queue);
2552 lp->l2_proto = ISDN_PROTO_L2_X75I;
2553 lp->l3_proto = ISDN_PROTO_L3_TRANS;
2554 lp->triggercps = 6000;
2555 lp->slavedelay = 10 * HZ;
2556 lp->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
2557 lp->onhtime = 10; /* Default hangup-time for saving costs */
2558 lp->dialmax = 1;
2559 /* Hangup before Callback, manual dial */
2560 lp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
2561 lp->cbdelay = 25; /* Wait 5 secs before Callback */
2562 lp->dialtimeout = -1; /* Infinite Dial-Timeout */
2563 lp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
2564 lp->dialstarted = 0; /* Jiffies of last dial-start */
2565 lp->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
2566}
2567
2568/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 * Allocate a new network-interface and initialize its data structures.
2570 */
2571char *
2572isdn_net_new(char *name, struct net_device *master)
2573{
2574 isdn_net_dev *netdev;
2575
2576 /* Avoid creating an existing interface */
2577 if (isdn_net_findif(name)) {
2578 printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
2579 return NULL;
2580 }
Karsten Keild62a38d2007-10-08 20:37:11 -07002581 if (name == NULL)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002582 return NULL;
Burman Yan41f96932006-12-08 02:39:35 -08002583 if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
2585 return NULL;
2586 }
Karsten Keild62a38d2007-10-08 20:37:11 -07002587 netdev->dev = alloc_netdev(sizeof(isdn_net_local), name, _isdn_setup);
2588 if (!netdev->dev) {
2589 printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 kfree(netdev);
2591 return NULL;
2592 }
Wang Chen838361f2008-12-03 15:49:46 -08002593 netdev->local = netdev_priv(netdev->dev);
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 if (master) {
2596 /* Device shall be a slave */
Wang Chen838361f2008-12-03 15:49:46 -08002597 struct net_device *p = MASTER_TO_SLAVE(master);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 struct net_device *q = master;
2599
2600 netdev->local->master = master;
2601 /* Put device at end of slave-chain */
2602 while (p) {
2603 q = p;
Wang Chen838361f2008-12-03 15:49:46 -08002604 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 }
Wang Chen838361f2008-12-03 15:49:46 -08002606 MASTER_TO_SLAVE(q) = netdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 } else {
2608 /* Device shall be a master */
2609 /*
2610 * Watchdog timer (currently) for master only.
2611 */
Karsten Keild62a38d2007-10-08 20:37:11 -07002612 netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
2613 if (register_netdev(netdev->dev) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 printk(KERN_WARNING "isdn_net: Could not register net-device\n");
Karsten Keild62a38d2007-10-08 20:37:11 -07002615 free_netdev(netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 kfree(netdev);
2617 return NULL;
2618 }
2619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 netdev->queue = netdev->local;
2621 spin_lock_init(&netdev->queue_lock);
2622
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 netdev->local->netdev = netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624
David Howellsc4028952006-11-22 14:57:56 +00002625 INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 spin_lock_init(&netdev->local->xmit_lock);
2627
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 /* Put into to netdev-chain */
2629 netdev->next = (void *) dev->netdev;
2630 dev->netdev = netdev;
Karsten Keild62a38d2007-10-08 20:37:11 -07002631 return netdev->dev->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632}
2633
2634char *
2635isdn_net_newslave(char *parm)
2636{
2637 char *p = strchr(parm, ',');
2638 isdn_net_dev *n;
2639 char newname[10];
2640
2641 if (p) {
2642 /* Slave-Name MUST not be empty */
2643 if (!strlen(p + 1))
2644 return NULL;
2645 strcpy(newname, p + 1);
2646 *p = 0;
2647 /* Master must already exist */
2648 if (!(n = isdn_net_findif(parm)))
2649 return NULL;
2650 /* Master must be a real interface, not a slave */
2651 if (n->local->master)
2652 return NULL;
2653 /* Master must not be started yet */
2654 if (isdn_net_device_started(n))
2655 return NULL;
Karsten Keild62a38d2007-10-08 20:37:11 -07002656 return (isdn_net_new(newname, n->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 }
2658 return NULL;
2659}
2660
2661/*
2662 * Set interface-parameters.
2663 * Always set all parameters, so the user-level application is responsible
2664 * for not overwriting existing setups. It has to get the current
2665 * setup first, if only selected parameters are to be changed.
2666 */
2667int
2668isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
2669{
2670 isdn_net_dev *p = isdn_net_findif(cfg->name);
2671 ulong features;
2672 int i;
2673 int drvidx;
2674 int chidx;
2675 char drvid[25];
2676
2677 if (p) {
2678 isdn_net_local *lp = p->local;
2679
2680 /* See if any registered driver supports the features we want */
2681 features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
2682 ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
2683 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2684 if (dev->drv[i])
2685 if ((dev->drv[i]->interface->features & features) == features)
2686 break;
2687 if (i == ISDN_MAX_DRIVERS) {
2688 printk(KERN_WARNING "isdn_net: No driver with selected features\n");
2689 return -ENODEV;
2690 }
2691 if (lp->p_encap != cfg->p_encap){
2692#ifdef CONFIG_ISDN_X25
2693 struct concap_proto * cprot = p -> cprot;
2694#endif
2695 if (isdn_net_device_started(p)) {
2696 printk(KERN_WARNING "%s: cannot change encap when if is up\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002697 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 return -EBUSY;
2699 }
2700#ifdef CONFIG_ISDN_X25
2701 if( cprot && cprot -> pops )
2702 cprot -> pops -> proto_del ( cprot );
2703 p -> cprot = NULL;
2704 lp -> dops = NULL;
2705 /* ... , prepare for configuration of new one ... */
2706 switch ( cfg -> p_encap ){
2707 case ISDN_NET_ENCAP_X25IFACE:
2708 lp -> dops = &isdn_concap_reliable_dl_dops;
2709 }
2710 /* ... and allocate new one ... */
2711 p -> cprot = isdn_concap_new( cfg -> p_encap );
2712 /* p -> cprot == NULL now if p_encap is not supported
2713 by means of the concap_proto mechanism */
2714 /* the protocol is not configured yet; this will
2715 happen later when isdn_net_reset() is called */
2716#endif
2717 }
2718 switch ( cfg->p_encap ) {
2719 case ISDN_NET_ENCAP_SYNCPPP:
2720#ifndef CONFIG_ISDN_PPP
2721 printk(KERN_WARNING "%s: SyncPPP support not configured\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002722 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723 return -EINVAL;
2724#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002725 p->dev->type = ARPHRD_PPP; /* change ARP type */
2726 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727#endif
2728 break;
2729 case ISDN_NET_ENCAP_X25IFACE:
2730#ifndef CONFIG_ISDN_X25
2731 printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
Denis V. Lunevc749b012007-10-15 12:52:20 -07002732 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733 return -EINVAL;
2734#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002735 p->dev->type = ARPHRD_X25; /* change ARP type */
2736 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737#endif
2738 break;
2739 case ISDN_NET_ENCAP_CISCOHDLCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 break;
2741 default:
2742 if( cfg->p_encap >= 0 &&
2743 cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
2744 break;
2745 printk(KERN_WARNING
2746 "%s: encapsulation protocol %d not supported\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002747 p->dev->name, cfg->p_encap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 return -EINVAL;
2749 }
2750 if (strlen(cfg->drvid)) {
2751 /* A bind has been requested ... */
2752 char *c,
2753 *e;
2754
2755 drvidx = -1;
2756 chidx = -1;
2757 strcpy(drvid, cfg->drvid);
2758 if ((c = strchr(drvid, ','))) {
2759 /* The channel-number is appended to the driver-Id with a comma */
2760 chidx = (int) simple_strtoul(c + 1, &e, 10);
2761 if (e == c)
2762 chidx = -1;
2763 *c = '\0';
2764 }
2765 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2766 /* Lookup driver-Id in array */
2767 if (!(strcmp(dev->drvid[i], drvid))) {
2768 drvidx = i;
2769 break;
2770 }
2771 if ((drvidx == -1) || (chidx == -1))
2772 /* Either driver-Id or channel-number invalid */
2773 return -ENODEV;
2774 } else {
2775 /* Parameters are valid, so get them */
2776 drvidx = lp->pre_device;
2777 chidx = lp->pre_channel;
2778 }
2779 if (cfg->exclusive > 0) {
2780 unsigned long flags;
2781
2782 /* If binding is exclusive, try to grab the channel */
2783 spin_lock_irqsave(&dev->lock, flags);
2784 if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
2785 lp->l2_proto, lp->l3_proto, drvidx,
2786 chidx, lp->msn)) < 0) {
2787 /* Grab failed, because desired channel is in use */
2788 lp->exclusive = -1;
2789 spin_unlock_irqrestore(&dev->lock, flags);
2790 return -EBUSY;
2791 }
2792 /* All went ok, so update isdninfo */
2793 dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2794 isdn_info_update();
2795 spin_unlock_irqrestore(&dev->lock, flags);
2796 lp->exclusive = i;
2797 } else {
2798 /* Non-exclusive binding or unbind. */
2799 lp->exclusive = -1;
2800 if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2801 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2802 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2803 drvidx = -1;
2804 chidx = -1;
2805 }
2806 }
Karsten Keil0f138642007-11-22 12:43:13 +01002807 strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 lp->pre_device = drvidx;
2809 lp->pre_channel = chidx;
2810 lp->onhtime = cfg->onhtime;
2811 lp->charge = cfg->charge;
2812 lp->l2_proto = cfg->l2_proto;
2813 lp->l3_proto = cfg->l3_proto;
2814 lp->cbdelay = cfg->cbdelay;
2815 lp->dialmax = cfg->dialmax;
2816 lp->triggercps = cfg->triggercps;
2817 lp->slavedelay = cfg->slavedelay * HZ;
2818 lp->pppbind = cfg->pppbind;
2819 lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
2820 lp->dialwait = cfg->dialwait * HZ;
2821 if (cfg->secure)
2822 lp->flags |= ISDN_NET_SECURE;
2823 else
2824 lp->flags &= ~ISDN_NET_SECURE;
2825 if (cfg->cbhup)
2826 lp->flags |= ISDN_NET_CBHUP;
2827 else
2828 lp->flags &= ~ISDN_NET_CBHUP;
2829 switch (cfg->callback) {
2830 case 0:
2831 lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
2832 break;
2833 case 1:
2834 lp->flags |= ISDN_NET_CALLBACK;
2835 lp->flags &= ~ISDN_NET_CBOUT;
2836 break;
2837 case 2:
2838 lp->flags |= ISDN_NET_CBOUT;
2839 lp->flags &= ~ISDN_NET_CALLBACK;
2840 break;
2841 }
2842 lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
2843 if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
2844 /* old isdnctrl version, where only 0 or 1 is given */
2845 printk(KERN_WARNING
2846 "Old isdnctrl version detected! Please update.\n");
2847 lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
2848 }
2849 else {
2850 lp->flags |= cfg->dialmode; /* turn on selected bits */
2851 }
2852 if (cfg->chargehup)
2853 lp->hupflags |= ISDN_CHARGEHUP;
2854 else
2855 lp->hupflags &= ~ISDN_CHARGEHUP;
2856 if (cfg->ihup)
2857 lp->hupflags |= ISDN_INHUP;
2858 else
2859 lp->hupflags &= ~ISDN_INHUP;
2860 if (cfg->chargeint > 10) {
2861 lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
2862 lp->chargeint = cfg->chargeint * HZ;
2863 }
2864 if (cfg->p_encap != lp->p_encap) {
2865 if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
Karsten Keild62a38d2007-10-08 20:37:11 -07002866 p->dev->header_ops = NULL;
2867 p->dev->flags = IFF_NOARP|IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 } else {
Karsten Keild62a38d2007-10-08 20:37:11 -07002869 p->dev->header_ops = &isdn_header_ops;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002870 if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
Karsten Keild62a38d2007-10-08 20:37:11 -07002871 p->dev->flags = IFF_BROADCAST | IFF_MULTICAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002872 else
Karsten Keild62a38d2007-10-08 20:37:11 -07002873 p->dev->flags = IFF_NOARP|IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874 }
2875 }
2876 lp->p_encap = cfg->p_encap;
2877 return 0;
2878 }
2879 return -ENODEV;
2880}
2881
2882/*
2883 * Perform get-interface-parameters.ioctl
2884 */
2885int
2886isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
2887{
2888 isdn_net_dev *p = isdn_net_findif(cfg->name);
2889
2890 if (p) {
2891 isdn_net_local *lp = p->local;
2892
2893 strcpy(cfg->eaz, lp->msn);
2894 cfg->exclusive = lp->exclusive;
2895 if (lp->pre_device >= 0) {
2896 sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
2897 lp->pre_channel);
2898 } else
2899 cfg->drvid[0] = '\0';
2900 cfg->onhtime = lp->onhtime;
2901 cfg->charge = lp->charge;
2902 cfg->l2_proto = lp->l2_proto;
2903 cfg->l3_proto = lp->l3_proto;
2904 cfg->p_encap = lp->p_encap;
2905 cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
2906 cfg->callback = 0;
2907 if (lp->flags & ISDN_NET_CALLBACK)
2908 cfg->callback = 1;
2909 if (lp->flags & ISDN_NET_CBOUT)
2910 cfg->callback = 2;
2911 cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
2912 cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
2913 cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
2914 cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
2915 cfg->cbdelay = lp->cbdelay;
2916 cfg->dialmax = lp->dialmax;
2917 cfg->triggercps = lp->triggercps;
2918 cfg->slavedelay = lp->slavedelay / HZ;
2919 cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
2920 (lp->chargeint / HZ) : 0;
2921 cfg->pppbind = lp->pppbind;
2922 cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
2923 cfg->dialwait = lp->dialwait / HZ;
Karsten Keilfaca94f2007-10-15 02:11:44 -07002924 if (lp->slave) {
2925 if (strlen(lp->slave->name) > 8)
2926 strcpy(cfg->slave, "too-long");
2927 else
2928 strcpy(cfg->slave, lp->slave->name);
2929 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 cfg->slave[0] = '\0';
Karsten Keilfaca94f2007-10-15 02:11:44 -07002931 if (lp->master) {
2932 if (strlen(lp->master->name) > 8)
2933 strcpy(cfg->master, "too-long");
2934 strcpy(cfg->master, lp->master->name);
2935 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 cfg->master[0] = '\0';
2937 return 0;
2938 }
2939 return -ENODEV;
2940}
2941
2942/*
2943 * Add a phone-number to an interface.
2944 */
2945int
2946isdn_net_addphone(isdn_net_ioctl_phone * phone)
2947{
2948 isdn_net_dev *p = isdn_net_findif(phone->name);
2949 isdn_net_phone *n;
2950
2951 if (p) {
Robert P. J. Day5cbded52006-12-13 00:35:56 -08002952 if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 return -ENOMEM;
Karsten Keil0f138642007-11-22 12:43:13 +01002954 strlcpy(n->num, phone->phone, sizeof(n->num));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 n->next = p->local->phone[phone->outgoing & 1];
2956 p->local->phone[phone->outgoing & 1] = n;
2957 return 0;
2958 }
2959 return -ENODEV;
2960}
2961
2962/*
2963 * Copy a string of all phone-numbers of an interface to user space.
2964 * This might sleep and must be called with the isdn semaphore down.
2965 */
2966int
2967isdn_net_getphones(isdn_net_ioctl_phone * phone, char __user *phones)
2968{
2969 isdn_net_dev *p = isdn_net_findif(phone->name);
2970 int inout = phone->outgoing & 1;
2971 int more = 0;
2972 int count = 0;
2973 isdn_net_phone *n;
2974
2975 if (!p)
2976 return -ENODEV;
2977 inout &= 1;
2978 for (n = p->local->phone[inout]; n; n = n->next) {
2979 if (more) {
2980 put_user(' ', phones++);
2981 count++;
2982 }
2983 if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
2984 return -EFAULT;
2985 }
2986 phones += strlen(n->num);
2987 count += strlen(n->num);
2988 more = 1;
2989 }
2990 put_user(0, phones);
2991 count++;
2992 return count;
2993}
2994
2995/*
2996 * Copy a string containing the peer's phone number of a connected interface
2997 * to user space.
2998 */
2999int
3000isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
3001{
3002 isdn_net_dev *p = isdn_net_findif(phone->name);
3003 int ch, dv, idx;
3004
Karsten Keilfaca94f2007-10-15 02:11:44 -07003005 if (!p)
3006 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 /*
3008 * Theoretical race: while this executes, the remote number might
3009 * become invalid (hang up) or change (new connection), resulting
3010 * in (partially) wrong number copied to user. This race
3011 * currently ignored.
3012 */
3013 ch = p->local->isdn_channel;
3014 dv = p->local->isdn_device;
Karsten Keilfaca94f2007-10-15 02:11:44 -07003015 if(ch < 0 && dv < 0)
3016 return -ENOTCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 idx = isdn_dc2minor(dv, ch);
Karsten Keilfaca94f2007-10-15 02:11:44 -07003018 if (idx <0 )
3019 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 /* for pre-bound channels, we need this extra check */
Karsten Keilfaca94f2007-10-15 02:11:44 -07003021 if (strncmp(dev->num[idx], "???", 3) == 0)
3022 return -ENOTCONN;
3023 strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
3024 phone->outgoing = USG_OUTGOING(dev->usage[idx]);
3025 if (copy_to_user(peer, phone, sizeof(*peer)))
3026 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 return 0;
3028}
3029/*
3030 * Delete a phone-number from an interface.
3031 */
3032int
3033isdn_net_delphone(isdn_net_ioctl_phone * phone)
3034{
3035 isdn_net_dev *p = isdn_net_findif(phone->name);
3036 int inout = phone->outgoing & 1;
3037 isdn_net_phone *n;
3038 isdn_net_phone *m;
3039
3040 if (p) {
3041 n = p->local->phone[inout];
3042 m = NULL;
3043 while (n) {
3044 if (!strcmp(n->num, phone->phone)) {
3045 if (p->local->dial == n)
3046 p->local->dial = n->next;
3047 if (m)
3048 m->next = n->next;
3049 else
3050 p->local->phone[inout] = n->next;
3051 kfree(n);
3052 return 0;
3053 }
3054 m = n;
3055 n = (isdn_net_phone *) n->next;
3056 }
3057 return -EINVAL;
3058 }
3059 return -ENODEV;
3060}
3061
3062/*
3063 * Delete all phone-numbers of an interface.
3064 */
3065static int
3066isdn_net_rmallphone(isdn_net_dev * p)
3067{
3068 isdn_net_phone *n;
3069 isdn_net_phone *m;
3070 int i;
3071
3072 for (i = 0; i < 2; i++) {
3073 n = p->local->phone[i];
3074 while (n) {
3075 m = n->next;
3076 kfree(n);
3077 n = m;
3078 }
3079 p->local->phone[i] = NULL;
3080 }
3081 p->local->dial = NULL;
3082 return 0;
3083}
3084
3085/*
3086 * Force a hangup of a network-interface.
3087 */
3088int
3089isdn_net_force_hangup(char *name)
3090{
3091 isdn_net_dev *p = isdn_net_findif(name);
3092 struct net_device *q;
3093
3094 if (p) {
3095 if (p->local->isdn_device < 0)
3096 return 1;
3097 q = p->local->slave;
3098 /* If this interface has slaves, do a hangup for them also. */
3099 while (q) {
3100 isdn_net_hangup(q);
Wang Chen838361f2008-12-03 15:49:46 -08003101 q = MASTER_TO_SLAVE(q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 }
Karsten Keild62a38d2007-10-08 20:37:11 -07003103 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 return 0;
3105 }
3106 return -ENODEV;
3107}
3108
3109/*
3110 * Helper-function for isdn_net_rm: Do the real work.
3111 */
3112static int
3113isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
3114{
3115 u_long flags;
3116
3117 if (isdn_net_device_started(p)) {
3118 return -EBUSY;
3119 }
3120#ifdef CONFIG_ISDN_X25
3121 if( p -> cprot && p -> cprot -> pops )
3122 p -> cprot -> pops -> proto_del ( p -> cprot );
3123#endif
3124 /* Free all phone-entries */
3125 isdn_net_rmallphone(p);
3126 /* If interface is bound exclusive, free channel-usage */
3127 if (p->local->exclusive != -1)
3128 isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
3129 if (p->local->master) {
3130 /* It's a slave-device, so update master's slave-pointer if necessary */
Wang Chen838361f2008-12-03 15:49:46 -08003131 if (((isdn_net_local *) ISDN_MASTER_PRIV(p->local))->slave ==
3132 p->dev)
3133 ((isdn_net_local *)ISDN_MASTER_PRIV(p->local))->slave =
3134 p->local->slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135 } else {
3136 /* Unregister only if it's a master-device */
Karsten Keild62a38d2007-10-08 20:37:11 -07003137 unregister_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 }
3139 /* Unlink device from chain */
3140 spin_lock_irqsave(&dev->lock, flags);
3141 if (q)
3142 q->next = p->next;
3143 else
3144 dev->netdev = p->next;
3145 if (p->local->slave) {
3146 /* If this interface has a slave, remove it also */
Karsten Keilfaca94f2007-10-15 02:11:44 -07003147 char *slavename = p->local->slave->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 isdn_net_dev *n = dev->netdev;
3149 q = NULL;
3150 while (n) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003151 if (!strcmp(n->dev->name, slavename)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003152 spin_unlock_irqrestore(&dev->lock, flags);
3153 isdn_net_realrm(n, q);
3154 spin_lock_irqsave(&dev->lock, flags);
3155 break;
3156 }
3157 q = n;
Karsten Keilfaca94f2007-10-15 02:11:44 -07003158 n = (isdn_net_dev *)n->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 }
3160 }
3161 spin_unlock_irqrestore(&dev->lock, flags);
3162 /* If no more net-devices remain, disable auto-hangup timer */
3163 if (dev->netdev == NULL)
3164 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
Karsten Keild62a38d2007-10-08 20:37:11 -07003165 free_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 kfree(p);
3167
3168 return 0;
3169}
3170
3171/*
3172 * Remove a single network-interface.
3173 */
3174int
3175isdn_net_rm(char *name)
3176{
3177 u_long flags;
3178 isdn_net_dev *p;
3179 isdn_net_dev *q;
3180
3181 /* Search name in netdev-chain */
3182 spin_lock_irqsave(&dev->lock, flags);
3183 p = dev->netdev;
3184 q = NULL;
3185 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003186 if (!strcmp(p->dev->name, name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 spin_unlock_irqrestore(&dev->lock, flags);
3188 return (isdn_net_realrm(p, q));
3189 }
3190 q = p;
3191 p = (isdn_net_dev *) p->next;
3192 }
3193 spin_unlock_irqrestore(&dev->lock, flags);
3194 /* If no more net-devices remain, disable auto-hangup timer */
3195 if (dev->netdev == NULL)
3196 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3197 return -ENODEV;
3198}
3199
3200/*
3201 * Remove all network-interfaces
3202 */
3203int
3204isdn_net_rmall(void)
3205{
3206 u_long flags;
3207 int ret;
3208
3209 /* Walk through netdev-chain */
3210 spin_lock_irqsave(&dev->lock, flags);
3211 while (dev->netdev) {
3212 if (!dev->netdev->local->master) {
3213 /* Remove master-devices only, slaves get removed with their master */
3214 spin_unlock_irqrestore(&dev->lock, flags);
3215 if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
3216 return ret;
3217 }
3218 spin_lock_irqsave(&dev->lock, flags);
3219 }
3220 }
3221 dev->netdev = NULL;
3222 spin_unlock_irqrestore(&dev->lock, flags);
3223 return 0;
3224}