blob: c138f66f26595bcfe714f1b3e1f0838ef4ab6c3f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, network interfaces and related functions (linklevel).
4 *
5 * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
Joe Perches475be4d2012-02-19 19:52:38 -080012 * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 * guy@traverse.com.au
14 * Outgoing calls - looks for a 'V' in first char of dialed number
15 * Incoming calls - checks first character of eaz as follows:
16 * Numeric - accept DATA only - original functionality
17 * 'V' - accept VOICE (DOV) only
18 * 'B' - accept BOTH DATA and DOV types
19 *
20 * Jan 2001: fix CISCO HDLC Bjoern A. Zeeb <i4l@zabbadoz.net>
Joe Perches475be4d2012-02-19 19:52:38 -080021 * for info on the protocol, see
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
23 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/isdn.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090026#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <net/arp.h>
28#include <net/dst.h>
29#include <net/pkt_sched.h>
30#include <linux/inetdevice.h>
31#include "isdn_common.h"
32#include "isdn_net.h"
33#ifdef CONFIG_ISDN_PPP
34#include "isdn_ppp.h"
35#endif
36#ifdef CONFIG_ISDN_X25
37#include <linux/concap.h>
38#include "isdn_concap.h"
39#endif
40
41
42/*
Joe Perches475be4d2012-02-19 19:52:38 -080043 * Outline of new tbusy handling:
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 *
45 * Old method, roughly spoken, consisted of setting tbusy when entering
46 * isdn_net_start_xmit() and at several other locations and clearing
47 * it from isdn_net_start_xmit() thread when sending was successful.
48 *
49 * With 2.3.x multithreaded network core, to prevent problems, tbusy should
50 * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
51 * condition is detected. Other threads (in particular isdn_net_stat_callb())
52 * are only allowed to clear tbusy.
53 *
54 * -HE
55 */
56
57/*
58 * About SOFTNET:
59 * Most of the changes were pretty obvious and basically done by HE already.
60 *
Geert Uytterhoeven3c7f3092015-03-03 11:58:08 +010061 * One problem of the isdn net device code is that it uses struct net_device
Joe Perches475be4d2012-02-19 19:52:38 -080062 * for masters and slaves. However, only master interface are registered to
63 * the network layer, and therefore, it only makes sense to call netif_*
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 * functions on them.
65 *
66 * --KG
67 */
68
Joe Perches475be4d2012-02-19 19:52:38 -080069/*
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 * Find out if the netdevice has been ifup-ed yet.
71 * For slaves, look at the corresponding master.
72 */
73static __inline__ int isdn_net_device_started(isdn_net_dev *n)
74{
75 isdn_net_local *lp = n->local;
76 struct net_device *dev;
Joe Perches475be4d2012-02-19 19:52:38 -080077
78 if (lp->master)
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 dev = lp->master;
80 else
Karsten Keild62a38d2007-10-08 20:37:11 -070081 dev = n->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 return netif_running(dev);
83}
84
85/*
86 * wake up the network -> net_device queue.
87 * For slaves, wake the corresponding master interface.
88 */
89static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
90{
Joe Perches475be4d2012-02-19 19:52:38 -080091 if (lp->master)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092 netif_wake_queue(lp->master);
93 else
Karsten Keild62a38d2007-10-08 20:37:11 -070094 netif_wake_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095}
96
97/*
98 * stop the network -> net_device queue.
99 * For slaves, stop the corresponding master interface.
100 */
101static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
102{
103 if (lp->master)
104 netif_stop_queue(lp->master);
105 else
Karsten Keild62a38d2007-10-08 20:37:11 -0700106 netif_stop_queue(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107}
108
109/*
110 * find out if the net_device which this lp belongs to (lp can be
Joe Perches475be4d2012-02-19 19:52:38 -0800111 * master or slave) is busy. It's busy iff all (master and slave)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 * queues are busy
113 */
114static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
115{
116 isdn_net_local *nlp;
117 isdn_net_dev *nd;
118 unsigned long flags;
119
120 if (!isdn_net_lp_busy(lp))
121 return 0;
122
123 if (lp->master)
Wang Chen838361f2008-12-03 15:49:46 -0800124 nd = ISDN_MASTER_PRIV(lp)->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 else
126 nd = lp->netdev;
Joe Perches475be4d2012-02-19 19:52:38 -0800127
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 spin_lock_irqsave(&nd->queue_lock, flags);
129 nlp = lp->next;
130 while (nlp != lp) {
131 if (!isdn_net_lp_busy(nlp)) {
132 spin_unlock_irqrestore(&nd->queue_lock, flags);
133 return 0;
134 }
135 nlp = nlp->next;
136 }
137 spin_unlock_irqrestore(&nd->queue_lock, flags);
138 return 1;
139}
140
141static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
142{
143 atomic_inc(&lp->frame_cnt);
144 if (isdn_net_device_busy(lp))
145 isdn_net_device_stop_queue(lp);
146}
147
148static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
149{
150 atomic_dec(&lp->frame_cnt);
151
152 if (!(isdn_net_device_busy(lp))) {
153 if (!skb_queue_empty(&lp->super_tx_queue)) {
154 schedule_work(&lp->tqueue);
155 } else {
156 isdn_net_device_wake_queue(lp);
157 }
Joe Perches475be4d2012-02-19 19:52:38 -0800158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159}
160
161static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
162{
163 atomic_set(&lp->frame_cnt, 0);
164}
165
Joe Perches475be4d2012-02-19 19:52:38 -0800166/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 * to be safe.
168 * For 2.3.x we push it up to 20 secs, because call establishment
Joe Perches475be4d2012-02-19 19:52:38 -0800169 * (in particular callback) may take such a long time, and we
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170 * don't want confusing messages in the log. However, there is a slight
171 * possibility that this large timeout will break other things like MPPP,
172 * which might rely on the tx timeout. If so, we'll find out this way...
173 */
174
Joe Perches475be4d2012-02-19 19:52:38 -0800175#define ISDN_NET_TX_TIMEOUT (20 * HZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
177/* Prototypes */
178
Adrian Bunk3e206b02005-06-25 14:58:35 -0700179static int isdn_net_force_dial_lp(isdn_net_local *);
Stephen Hemminger8b62ff22009-08-31 19:50:44 +0000180static netdev_tx_t isdn_net_start_xmit(struct sk_buff *,
Joe Perches475be4d2012-02-19 19:52:38 -0800181 struct net_device *);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
183static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
184static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
185
186char *isdn_net_revision = "$Revision: 1.1.2.2 $";
187
Joe Perches475be4d2012-02-19 19:52:38 -0800188/*
189 * Code for raw-networking over ISDN
190 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
192static void
193isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
194{
Joe Perches475be4d2012-02-19 19:52:38 -0800195 if (skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 u_short proto = ntohs(skb->protocol);
198
199 printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
200 dev->name,
201 (reason != NULL) ? reason : "unknown",
202 (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
Joe Perches475be4d2012-02-19 19:52:38 -0800203
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 dst_link_failure(skb);
205 }
206 else { /* dial not triggered by rawIP packet */
207 printk(KERN_DEBUG "isdn_net: %s: %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -0800208 dev->name,
209 (reason != NULL) ? reason : "reason unknown");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 }
211}
212
213static void
214isdn_net_reset(struct net_device *dev)
215{
216#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800217 struct concap_device_ops *dops =
218 ((isdn_net_local *)netdev_priv(dev))->dops;
219 struct concap_proto *cprot =
220 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221#endif
222#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800223 if (cprot && cprot->pops && dops)
224 cprot->pops->restart(cprot, dev, dops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225#endif
226}
227
228/* Open/initialize the board. */
229static int
230isdn_net_open(struct net_device *dev)
231{
232 int i;
233 struct net_device *p;
234 struct in_device *in_dev;
235
236 /* moved here from isdn_net_reset, because only the master has an
237 interface associated which is supposed to be started. BTW:
238 we need to call netif_start_queue, not netif_wake_queue here */
239 netif_start_queue(dev);
240
241 isdn_net_reset(dev);
242 /* Fill in the MAC-level header (not needed, but for compatibility... */
243 for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
244 dev->dev_addr[i] = 0xfc;
245 if ((in_dev = dev->ip_ptr) != NULL) {
246 /*
247 * Any address will do - we take the first
248 */
249 struct in_ifaddr *ifa = in_dev->ifa_list;
250 if (ifa != NULL)
Joe Perches475be4d2012-02-19 19:52:38 -0800251 memcpy(dev->dev_addr + 2, &ifa->ifa_local, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 }
253
254 /* If this interface has slaves, start them also */
Wang Chen838361f2008-12-03 15:49:46 -0800255 p = MASTER_TO_SLAVE(dev);
256 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 while (p) {
258 isdn_net_reset(p);
Wang Chen838361f2008-12-03 15:49:46 -0800259 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 }
261 }
262 isdn_lock_drivers();
263 return 0;
264}
265
266/*
267 * Assign an ISDN-channel to a net-interface
268 */
269static void
Joe Perches475be4d2012-02-19 19:52:38 -0800270isdn_net_bind_channel(isdn_net_local *lp, int idx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 lp->flags |= ISDN_NET_CONNECTED;
273 lp->isdn_device = dev->drvmap[idx];
274 lp->isdn_channel = dev->chanmap[idx];
275 dev->rx_netdev[idx] = lp->netdev;
276 dev->st_netdev[idx] = lp->netdev;
277}
278
279/*
280 * unbind a net-interface (resets interface after an error)
281 */
282static void
Joe Perches475be4d2012-02-19 19:52:38 -0800283isdn_net_unbind_channel(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284{
285 skb_queue_purge(&lp->super_tx_queue);
286
287 if (!lp->master) { /* reset only master device */
288 /* Moral equivalent of dev_purge_queues():
289 BEWARE! This chunk of code cannot be called from hardware
290 interrupt handler. I hope it is true. --ANK
Joe Perches475be4d2012-02-19 19:52:38 -0800291 */
David S. Miller5aa70992008-07-08 22:59:10 -0700292 qdisc_reset_all_tx(lp->netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294 lp->dialstate = 0;
295 dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
296 dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
Paul Bollebae58432009-01-14 14:41:00 -0800297 if (lp->isdn_device != -1 && lp->isdn_channel != -1)
298 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
299 ISDN_USAGE_NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 lp->flags &= ~ISDN_NET_CONNECTED;
301 lp->isdn_device = -1;
302 lp->isdn_channel = -1;
303}
304
305/*
306 * Perform auto-hangup and cps-calculation for net-interfaces.
307 *
308 * auto-hangup:
309 * Increment idle-counter (this counter is reset on any incoming or
310 * outgoing packet), if counter exceeds configured limit either do a
311 * hangup immediately or - if configured - wait until just before the next
312 * charge-info.
313 *
314 * cps-calculation (needed for dynamic channel-bundling):
315 * Since this function is called every second, simply reset the
316 * byte-counter of the interface after copying it to the cps-variable.
317 */
Adrian Bunk3e206b02005-06-25 14:58:35 -0700318static unsigned long last_jiffies = -HZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320void
321isdn_net_autohup(void)
322{
323 isdn_net_dev *p = dev->netdev;
324 int anymore;
325
326 anymore = 0;
327 while (p) {
328 isdn_net_local *l = p->local;
329 if (jiffies == last_jiffies)
330 l->cps = l->transcount;
331 else
332 l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
333 l->transcount = 0;
334 if (dev->net_verbose > 3)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700335 printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
337 anymore = 1;
338 l->huptimer++;
339 /*
340 * if there is some dialmode where timeout-hangup
341 * should _not_ be done, check for that here
342 */
343 if ((l->onhtime) &&
344 (l->huptimer > l->onhtime))
345 {
346 if (l->hupflags & ISDN_MANCHARGE &&
347 l->hupflags & ISDN_CHARGEHUP) {
348 while (time_after(jiffies, l->chargetime + l->chargeint))
349 l->chargetime += l->chargeint;
350 if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
351 if (l->outgoing || l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700352 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353 } else if (l->outgoing) {
354 if (l->hupflags & ISDN_CHARGEHUP) {
355 if (l->hupflags & ISDN_WAITCHARGE) {
356 printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700357 p->dev->name, l->hupflags);
Karsten Keild62a38d2007-10-08 20:37:11 -0700358 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
360 printk(KERN_DEBUG
361 "isdn_net: %s: chtime = %lu, chint = %d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -0700362 p->dev->name, l->chargetime, l->chargeint);
Karsten Keild62a38d2007-10-08 20:37:11 -0700363 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 }
365 } else
Karsten Keild62a38d2007-10-08 20:37:11 -0700366 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 } else if (l->hupflags & ISDN_INHUP)
Karsten Keild62a38d2007-10-08 20:37:11 -0700368 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 }
370
Joe Perches475be4d2012-02-19 19:52:38 -0800371 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
Karsten Keild62a38d2007-10-08 20:37:11 -0700372 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 break;
374 }
375 }
376 p = (isdn_net_dev *) p->next;
377 }
378 last_jiffies = jiffies;
379 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
380}
381
382static void isdn_net_lp_disconnected(isdn_net_local *lp)
383{
384 isdn_net_rm_from_bundle(lp);
385}
386
387/*
388 * Handle status-messages from ISDN-interfacecard.
389 * This function is called from within the main-status-dispatcher
390 * isdn_status_callback, which itself is called from the low-level driver.
391 * Return: 1 = Event handled, 0 = not for us or unknown Event.
392 */
393int
394isdn_net_stat_callback(int idx, isdn_ctrl *c)
395{
396 isdn_net_dev *p = dev->st_netdev[idx];
397 int cmd = c->command;
398
399 if (p) {
400 isdn_net_local *lp = p->local;
401#ifdef CONFIG_ISDN_X25
402 struct concap_proto *cprot = lp->netdev->cprot;
403 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
404#endif
405 switch (cmd) {
Joe Perches475be4d2012-02-19 19:52:38 -0800406 case ISDN_STAT_BSENT:
407 /* A packet has successfully been sent out */
408 if ((lp->flags & ISDN_NET_CONNECTED) &&
409 (!lp->dialstate)) {
410 isdn_net_dec_frame_cnt(lp);
411 lp->stats.tx_packets++;
412 lp->stats.tx_bytes += c->parm.length;
413 }
414 return 1;
415 case ISDN_STAT_DCONN:
416 /* D-Channel is up */
417 switch (lp->dialstate) {
418 case 4:
419 case 7:
420 case 8:
421 lp->dialstate++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 return 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800423 case 12:
424 lp->dialstate = 5;
425 return 1;
426 }
427 break;
428 case ISDN_STAT_DHUP:
429 /* Either D-Channel-hangup or error during dialout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800431 /* If we are not connencted then dialing had
432 failed. If there are generic encap protocol
433 receiver routines signal the closure of
434 the link*/
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Joe Perches475be4d2012-02-19 19:52:38 -0800436 if (!(lp->flags & ISDN_NET_CONNECTED)
437 && pops && pops->disconn_ind)
438 pops->disconn_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -0800440 if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
441 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
442 isdn_net_ciscohdlck_disconnected(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800444 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
445 isdn_ppp_free(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446#endif
Joe Perches475be4d2012-02-19 19:52:38 -0800447 isdn_net_lp_disconnected(lp);
448 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
449 printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
450 printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
451 lp->charge);
452 isdn_net_unbind_channel(lp);
453 return 1;
454 }
455 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800457 case ISDN_STAT_BHUP:
458 /* B-Channel-hangup */
459 /* try if there are generic encap protocol
460 receiver routines and signal the closure of
461 the link */
462 if (pops && pops->disconn_ind) {
463 pops->disconn_ind(cprot);
464 return 1;
465 }
466 break;
467#endif /* CONFIG_ISDN_X25 */
468 case ISDN_STAT_BCONN:
469 /* B-Channel is up */
470 isdn_net_zero_frame_cnt(lp);
471 switch (lp->dialstate) {
472 case 5:
473 case 6:
474 case 7:
475 case 8:
476 case 9:
477 case 10:
478 case 12:
479 if (lp->dialstate <= 6) {
480 dev->usage[idx] |= ISDN_USAGE_OUTGOING;
481 isdn_info_update();
482 } else
483 dev->rx_netdev[idx] = p;
484 lp->dialstate = 0;
485 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
486 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
487 isdn_net_ciscohdlck_connected(lp);
488 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
489 if (lp->master) { /* is lp a slave? */
490 isdn_net_dev *nd = ISDN_MASTER_PRIV(lp)->netdev;
491 isdn_net_add_to_bundle(nd, lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 }
Joe Perches475be4d2012-02-19 19:52:38 -0800493 }
494 printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
495 /* If first Chargeinfo comes before B-Channel connect,
496 * we correct the timestamp here.
497 */
498 lp->chargetime = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Joe Perches475be4d2012-02-19 19:52:38 -0800500 /* reset dial-timeout */
501 lp->dialstarted = 0;
502 lp->dialwait_timer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800505 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
506 isdn_ppp_wakeup_daemon(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507#endif
508#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -0800509 /* try if there are generic concap receiver routines */
510 if (pops)
511 if (pops->connect_ind)
512 pops->connect_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -0800514 /* ppp needs to do negotiations first */
515 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
516 isdn_net_device_wake_queue(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 return 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800518 }
519 break;
520 case ISDN_STAT_NODCH:
521 /* No D-Channel avail. */
522 if (lp->dialstate == 4) {
523 lp->dialstate--;
524 return 1;
525 }
526 break;
527 case ISDN_STAT_CINF:
528 /* Charge-info from TelCo. Calculate interval between
529 * charge-infos and set timestamp for last info for
530 * usage by isdn_net_autohup()
531 */
532 lp->charge++;
533 if (lp->hupflags & ISDN_HAVECHARGE) {
534 lp->hupflags &= ~ISDN_WAITCHARGE;
535 lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
536 }
537 if (lp->hupflags & ISDN_WAITCHARGE)
538 lp->hupflags |= ISDN_HAVECHARGE;
539 lp->chargetime = jiffies;
540 printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
541 p->dev->name, lp->chargetime);
542 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544 }
545 return 0;
546}
547
548/*
549 * Perform dialout for net-interfaces and timeout-handling for
550 * D-Channel-up and B-Channel-up Messages.
551 * This function is initially called from within isdn_net_start_xmit() or
552 * or isdn_net_find_icall() after initializing the dialstate for an
553 * interface. If further calls are needed, the function schedules itself
554 * for a timer-callback via isdn_timer_function().
555 * The dialstate is also affected by incoming status-messages from
556 * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
557 */
558void
559isdn_net_dial(void)
560{
561 isdn_net_dev *p = dev->netdev;
562 int anymore = 0;
563 int i;
564 isdn_ctrl cmd;
Joe Perches475be4d2012-02-19 19:52:38 -0800565 u_char *phone_number;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
567 while (p) {
568 isdn_net_local *lp = p->local;
569
570#ifdef ISDN_DEBUG_NET_DIAL
571 if (lp->dialstate)
Karsten Keilfaca94f2007-10-15 02:11:44 -0700572 printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573#endif
574 switch (lp->dialstate) {
Joe Perches475be4d2012-02-19 19:52:38 -0800575 case 0:
576 /* Nothing to do for this interface */
577 break;
578 case 1:
579 /* Initiate dialout. Set phone-number-pointer to first number
580 * of interface.
581 */
582 lp->dial = lp->phone[1];
583 if (!lp->dial) {
584 printk(KERN_WARNING "%s: phone number deleted?\n",
585 p->dev->name);
586 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800588 }
589 anymore = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Joe Perches475be4d2012-02-19 19:52:38 -0800591 if (lp->dialtimeout > 0)
592 if (lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
593 lp->dialstarted = jiffies;
594 lp->dialwait_timer = 0;
595 }
596
597 lp->dialstate++;
598 /* Fall through */
599 case 2:
600 /* Prepare dialing. Clear EAZ, then set EAZ. */
601 cmd.driver = lp->isdn_device;
602 cmd.arg = lp->isdn_channel;
603 cmd.command = ISDN_CMD_CLREAZ;
604 isdn_command(&cmd);
605 sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
606 cmd.command = ISDN_CMD_SETEAZ;
607 isdn_command(&cmd);
608 lp->dialretry = 0;
609 anymore = 1;
610 lp->dialstate++;
611 /* Fall through */
612 case 3:
613 /* Setup interface, dial current phone-number, switch to next number.
614 * If list of phone-numbers is exhausted, increment
615 * retry-counter.
616 */
617 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
618 char *s;
619 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
620 s = "dial suppressed: isdn system stopped";
621 else
622 s = "dial suppressed: dialmode `off'";
623 isdn_net_unreachable(p->dev, NULL, s);
624 isdn_net_hangup(p->dev);
625 break;
626 }
627 cmd.driver = lp->isdn_device;
628 cmd.command = ISDN_CMD_SETL2;
629 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
630 isdn_command(&cmd);
631 cmd.driver = lp->isdn_device;
632 cmd.command = ISDN_CMD_SETL3;
633 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
634 isdn_command(&cmd);
635 cmd.driver = lp->isdn_device;
636 cmd.arg = lp->isdn_channel;
637 if (!lp->dial) {
638 printk(KERN_WARNING "%s: phone number deleted?\n",
639 p->dev->name);
640 isdn_net_hangup(p->dev);
641 break;
642 }
643 if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
644 lp->dialstate = 4;
645 printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
646 } else {
647 if (lp->dialtimeout > 0)
648 if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
649 lp->dialwait_timer = jiffies + lp->dialwait;
650 lp->dialstarted = 0;
651 isdn_net_unreachable(p->dev, NULL, "dial: timed out");
652 isdn_net_hangup(p->dev);
653 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 }
655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 cmd.driver = lp->isdn_device;
Joe Perches475be4d2012-02-19 19:52:38 -0800657 cmd.command = ISDN_CMD_DIAL;
658 cmd.parm.setup.si2 = 0;
659
660 /* check for DOV */
661 phone_number = lp->dial->num;
662 if ((*phone_number == 'v') ||
663 (*phone_number == 'V')) { /* DOV call */
664 cmd.parm.setup.si1 = 1;
665 } else { /* DATA call */
666 cmd.parm.setup.si1 = 7;
667 }
668
669 strcpy(cmd.parm.setup.phone, phone_number);
670 /*
671 * Switch to next number or back to start if at end of list.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 */
Joe Perches475be4d2012-02-19 19:52:38 -0800673 if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
674 lp->dial = lp->phone[1];
675 lp->dialretry++;
676
677 if (lp->dialretry > lp->dialmax) {
678 if (lp->dialtimeout == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 lp->dialwait_timer = jiffies + lp->dialwait;
680 lp->dialstarted = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800681 isdn_net_unreachable(p->dev, NULL, "dial: tried all numbers dialmax times");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 }
Joe Perches475be4d2012-02-19 19:52:38 -0800683 isdn_net_hangup(p->dev);
684 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 }
Joe Perches475be4d2012-02-19 19:52:38 -0800687 sprintf(cmd.parm.setup.eazmsn, "%s",
688 isdn_map_eaz2msn(lp->msn, cmd.driver));
689 i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
690 if (i >= 0) {
691 strcpy(dev->num[i], cmd.parm.setup.phone);
692 dev->usage[i] |= ISDN_USAGE_OUTGOING;
693 isdn_info_update();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 }
Joe Perches475be4d2012-02-19 19:52:38 -0800695 printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
696 lp->dialretry, cmd.parm.setup.phone,
697 (cmd.parm.setup.si1 == 1) ? "DOV" : "");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 lp->dtimer = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800699#ifdef ISDN_DEBUG_NET_DIAL
700 printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
701 lp->isdn_channel);
702#endif
703 isdn_command(&cmd);
704 }
705 lp->huptimer = 0;
706 lp->outgoing = 1;
707 if (lp->chargeint) {
708 lp->hupflags |= ISDN_HAVECHARGE;
709 lp->hupflags &= ~ISDN_WAITCHARGE;
710 } else {
711 lp->hupflags |= ISDN_WAITCHARGE;
712 lp->hupflags &= ~ISDN_HAVECHARGE;
713 }
714 anymore = 1;
715 lp->dialstate =
716 (lp->cbdelay &&
717 (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
718 break;
719 case 4:
720 /* Wait for D-Channel-connect.
721 * If timeout, switch back to state 3.
722 * Dialmax-handling moved to state 3.
723 */
724 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
725 lp->dialstate = 3;
726 anymore = 1;
727 break;
728 case 5:
729 /* Got D-Channel-Connect, send B-Channel-request */
730 cmd.driver = lp->isdn_device;
731 cmd.arg = lp->isdn_channel;
732 cmd.command = ISDN_CMD_ACCEPTB;
733 anymore = 1;
734 lp->dtimer = 0;
735 lp->dialstate++;
736 isdn_command(&cmd);
737 break;
738 case 6:
739 /* Wait for B- or D-Channel-connect. If timeout,
740 * switch back to state 3.
741 */
742#ifdef ISDN_DEBUG_NET_DIAL
743 printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
744#endif
745 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
746 lp->dialstate = 3;
747 anymore = 1;
748 break;
749 case 7:
750 /* Got incoming Call, setup L2 and L3 protocols,
751 * then wait for D-Channel-connect
752 */
753#ifdef ISDN_DEBUG_NET_DIAL
754 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
755#endif
756 cmd.driver = lp->isdn_device;
757 cmd.command = ISDN_CMD_SETL2;
758 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
759 isdn_command(&cmd);
760 cmd.driver = lp->isdn_device;
761 cmd.command = ISDN_CMD_SETL3;
762 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
763 isdn_command(&cmd);
764 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
765 isdn_net_hangup(p->dev);
766 else {
767 anymore = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 lp->dialstate++;
Joe Perches475be4d2012-02-19 19:52:38 -0800769 }
770 break;
771 case 9:
772 /* Got incoming D-Channel-Connect, send B-Channel-request */
773 cmd.driver = lp->isdn_device;
774 cmd.arg = lp->isdn_channel;
775 cmd.command = ISDN_CMD_ACCEPTB;
776 isdn_command(&cmd);
777 anymore = 1;
778 lp->dtimer = 0;
779 lp->dialstate++;
780 break;
781 case 8:
782 case 10:
783 /* Wait for B- or D-channel-connect */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784#ifdef ISDN_DEBUG_NET_DIAL
Joe Perches475be4d2012-02-19 19:52:38 -0800785 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786#endif
Joe Perches475be4d2012-02-19 19:52:38 -0800787 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
788 isdn_net_hangup(p->dev);
789 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 anymore = 1;
Joe Perches475be4d2012-02-19 19:52:38 -0800791 break;
792 case 11:
793 /* Callback Delay */
794 if (lp->dtimer++ > lp->cbdelay)
795 lp->dialstate = 1;
796 anymore = 1;
797 break;
798 case 12:
799 /* Remote does callback. Hangup after cbdelay, then wait for incoming
800 * call (in state 4).
801 */
802 if (lp->dtimer++ > lp->cbdelay)
803 {
804 printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 lp->dtimer = 0;
Joe Perches475be4d2012-02-19 19:52:38 -0800806 lp->dialstate = 4;
807 cmd.driver = lp->isdn_device;
808 cmd.command = ISDN_CMD_HANGUP;
809 cmd.arg = lp->isdn_channel;
810 isdn_command(&cmd);
811 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
812 }
813 anymore = 1;
814 break;
815 default:
816 printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
817 lp->dialstate, p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 }
819 p = (isdn_net_dev *) p->next;
820 }
821 isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
822}
823
824/*
825 * Perform hangup for a net-interface.
826 */
827void
828isdn_net_hangup(struct net_device *d)
829{
Joe Perchesa17531f2010-11-15 11:12:24 +0000830 isdn_net_local *lp = netdev_priv(d);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 isdn_ctrl cmd;
832#ifdef CONFIG_ISDN_X25
833 struct concap_proto *cprot = lp->netdev->cprot;
834 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
835#endif
836
837 if (lp->flags & ISDN_NET_CONNECTED) {
838 if (lp->slave != NULL) {
Wang Chen838361f2008-12-03 15:49:46 -0800839 isdn_net_local *slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 if (slp->flags & ISDN_NET_CONNECTED) {
841 printk(KERN_INFO
Joe Perches475be4d2012-02-19 19:52:38 -0800842 "isdn_net: hang up slave %s before %s\n",
843 lp->slave->name, d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 isdn_net_hangup(lp->slave);
845 }
846 }
Karsten Keilfaca94f2007-10-15 02:11:44 -0700847 printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848#ifdef CONFIG_ISDN_PPP
849 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
850 isdn_ppp_free(lp);
851#endif
852 isdn_net_lp_disconnected(lp);
853#ifdef CONFIG_ISDN_X25
854 /* try if there are generic encap protocol
855 receiver routines and signal the closure of
856 the link */
Joe Perches475be4d2012-02-19 19:52:38 -0800857 if (pops && pops->disconn_ind)
858 pops->disconn_ind(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859#endif /* CONFIG_ISDN_X25 */
860
861 cmd.driver = lp->isdn_device;
862 cmd.command = ISDN_CMD_HANGUP;
863 cmd.arg = lp->isdn_channel;
864 isdn_command(&cmd);
Karsten Keilfaca94f2007-10-15 02:11:44 -0700865 printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
867 }
868 isdn_net_unbind_channel(lp);
869}
870
871typedef struct {
Harvey Harrisonc19d0362008-11-20 04:10:51 -0800872 __be16 source;
873 __be16 dest;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874} ip_ports;
875
876static void
Joe Perches475be4d2012-02-19 19:52:38 -0800877isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878{
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -0700879 /* hopefully, this was set correctly */
880 const u_char *p = skb_network_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 unsigned short proto = ntohs(skb->protocol);
882 int data_ofs;
883 ip_ports *ipp;
884 char addinfo[100];
885
886 addinfo[0] = '\0';
887 /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
Simon Horman25b6e142013-05-28 20:34:23 +0000888 if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 /* fall back to old isdn_net_log_packet method() */
Joe Perches475be4d2012-02-19 19:52:38 -0800890 char *buf = skb->data;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
Karsten Keilfaca94f2007-10-15 02:11:44 -0700892 printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 p = buf;
894 proto = ETH_P_IP;
895 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -0800896 case ISDN_NET_ENCAP_IPTYP:
897 proto = ntohs(*(__be16 *)&buf[0]);
898 p = &buf[2];
899 break;
900 case ISDN_NET_ENCAP_ETHER:
901 proto = ntohs(*(__be16 *)&buf[12]);
902 p = &buf[14];
903 break;
904 case ISDN_NET_ENCAP_CISCOHDLC:
905 proto = ntohs(*(__be16 *)&buf[2]);
906 p = &buf[4];
907 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -0800909 case ISDN_NET_ENCAP_SYNCPPP:
910 proto = ntohs(skb->protocol);
911 p = &buf[IPPP_MAX_HEADER];
912 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913#endif
914 }
915 }
916 data_ofs = ((p[0] & 15) * 4);
917 switch (proto) {
Joe Perches475be4d2012-02-19 19:52:38 -0800918 case ETH_P_IP:
919 switch (p[9]) {
920 case 1:
921 strcpy(addinfo, " ICMP");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800923 case 2:
924 strcpy(addinfo, " IGMP");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800926 case 4:
927 strcpy(addinfo, " IPIP");
928 break;
929 case 6:
930 ipp = (ip_ports *) (&p[data_ofs]);
931 sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
932 ntohs(ipp->dest));
933 break;
934 case 8:
935 strcpy(addinfo, " EGP");
936 break;
937 case 12:
938 strcpy(addinfo, " PUP");
939 break;
940 case 17:
941 ipp = (ip_ports *) (&p[data_ofs]);
942 sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
943 ntohs(ipp->dest));
944 break;
945 case 22:
946 strcpy(addinfo, " IDP");
947 break;
948 }
949 printk(KERN_INFO "OPEN: %pI4 -> %pI4%s\n",
950 p + 12, p + 16, addinfo);
951 break;
952 case ETH_P_ARP:
953 printk(KERN_INFO "OPEN: ARP %pI4 -> *.*.*.* ?%pI4\n",
954 p + 14, p + 24);
955 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 }
957}
958
959/*
960 * this function is used to send supervisory data, i.e. data which was
961 * not received from the network layer, but e.g. frames from ipppd, CCP
962 * reset frames etc.
963 */
964void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
965{
966 if (in_irq()) {
Joe Perches475be4d2012-02-19 19:52:38 -0800967 // we can't grab the lock from irq context,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 // so we just queue the packet
969 skb_queue_tail(&lp->super_tx_queue, skb);
970 schedule_work(&lp->tqueue);
971 return;
972 }
973
974 spin_lock_bh(&lp->xmit_lock);
975 if (!isdn_net_lp_busy(lp)) {
976 isdn_net_writebuf_skb(lp, skb);
977 } else {
978 skb_queue_tail(&lp->super_tx_queue, skb);
979 }
980 spin_unlock_bh(&lp->xmit_lock);
981}
982
983/*
984 * called from tq_immediate
985 */
David Howellsc4028952006-11-22 14:57:56 +0000986static void isdn_net_softint(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987{
David Howellsc4028952006-11-22 14:57:56 +0000988 isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 struct sk_buff *skb;
990
991 spin_lock_bh(&lp->xmit_lock);
992 while (!isdn_net_lp_busy(lp)) {
993 skb = skb_dequeue(&lp->super_tx_queue);
994 if (!skb)
995 break;
Joe Perches475be4d2012-02-19 19:52:38 -0800996 isdn_net_writebuf_skb(lp, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 }
998 spin_unlock_bh(&lp->xmit_lock);
999}
1000
Joe Perches475be4d2012-02-19 19:52:38 -08001001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 * all frames sent from the (net) LL to a HL driver should go via this function
1003 * it's serialized by the caller holding the lp->xmit_lock spinlock
1004 */
1005void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
1006{
1007 int ret;
1008 int len = skb->len; /* save len */
1009
1010 /* before obtaining the lock the caller should have checked that
1011 the lp isn't busy */
1012 if (isdn_net_lp_busy(lp)) {
1013 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1014 goto error;
1015 }
1016
1017 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1018 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1019 goto error;
1020 }
1021 ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
1022 if (ret != len) {
1023 /* we should never get here */
Karsten Keilfaca94f2007-10-15 02:11:44 -07001024 printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 goto error;
1026 }
Joe Perches475be4d2012-02-19 19:52:38 -08001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 lp->transcount += len;
1029 isdn_net_inc_frame_cnt(lp);
1030 return;
1031
Joe Perches475be4d2012-02-19 19:52:38 -08001032error:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 dev_kfree_skb(skb);
1034 lp->stats.tx_errors++;
1035
1036}
1037
1038
1039/*
1040 * Helper function for isdn_net_start_xmit.
1041 * When called, the connection is already established.
1042 * Based on cps-calculation, check if device is overloaded.
1043 * If so, and if a slave exists, trigger dialing for it.
1044 * If any slave is online, deliver packets using a simple round robin
1045 * scheme.
1046 *
1047 * Return: 0 on success, !0 on failure.
1048 */
1049
1050static int
1051isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
1052{
1053 isdn_net_dev *nd;
1054 isdn_net_local *slp;
Joe Perchesa17531f2010-11-15 11:12:24 +00001055 isdn_net_local *lp = netdev_priv(ndev);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001056 int retv = NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Wang Chen838361f2008-12-03 15:49:46 -08001058 if (((isdn_net_local *) netdev_priv(ndev))->master) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1060 dev_kfree_skb(skb);
Patrick McHardyec634fe2009-07-05 19:23:38 -07001061 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
1064 /* For the other encaps the header has already been built */
1065#ifdef CONFIG_ISDN_PPP
1066 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1067 return isdn_ppp_xmit(skb, ndev);
1068 }
1069#endif
Wang Chen838361f2008-12-03 15:49:46 -08001070 nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 lp = isdn_net_get_locked_lp(nd);
1072 if (!lp) {
1073 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
Patrick McHardy5b548142009-06-12 06:22:29 +00001074 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075 }
1076 /* we have our lp locked from now on */
1077
1078 /* Reset hangup-timeout */
1079 lp->huptimer = 0; // FIXME?
1080 isdn_net_writebuf_skb(lp, skb);
1081 spin_unlock_bh(&lp->xmit_lock);
1082
1083 /* the following stuff is here for backwards compatibility.
1084 * in future, start-up and hangup of slaves (based on current load)
1085 * should move to userspace and get based on an overall cps
1086 * calculation
1087 */
1088 if (lp->cps > lp->triggercps) {
1089 if (lp->slave) {
1090 if (!lp->sqfull) {
1091 /* First time overload: set timestamp only */
1092 lp->sqfull = 1;
1093 lp->sqfull_stamp = jiffies;
1094 } else {
1095 /* subsequent overload: if slavedelay exceeded, start dialing */
1096 if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
Wang Chen838361f2008-12-03 15:49:46 -08001097 slp = ISDN_SLAVE_PRIV(lp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 if (!(slp->flags & ISDN_NET_CONNECTED)) {
Wang Chen838361f2008-12-03 15:49:46 -08001099 isdn_net_force_dial_lp(ISDN_SLAVE_PRIV(lp));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 }
1101 }
1102 }
1103 }
1104 } else {
1105 if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
1106 lp->sqfull = 0;
1107 }
1108 /* this is a hack to allow auto-hangup for slaves on moderate loads */
1109 nd->queue = nd->local;
1110 }
1111
1112 return retv;
1113
1114}
1115
1116static void
1117isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
1118{
Joe Perchesa17531f2010-11-15 11:12:24 +00001119 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (!skb)
1121 return;
1122 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001123 const int pullsize = skb_network_offset(skb) - ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 if (pullsize > 0) {
1125 printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
1126 skb_pull(skb, pullsize);
1127 }
1128 }
1129}
1130
1131
Joe Perches475be4d2012-02-19 19:52:38 -08001132static void isdn_net_tx_timeout(struct net_device *ndev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133{
Joe Perchesa17531f2010-11-15 11:12:24 +00001134 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135
1136 printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
Joe Perches475be4d2012-02-19 19:52:38 -08001137 if (!lp->dialstate) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 lp->stats.tx_errors++;
Joe Perches475be4d2012-02-19 19:52:38 -08001139 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 * There is a certain probability that this currently
1141 * works at all because if we always wake up the interface,
1142 * then upper layer will try to send the next packet
1143 * immediately. And then, the old clean_up logic in the
1144 * driver will hopefully continue to work as it used to do.
1145 *
1146 * This is rather primitive right know, we better should
1147 * clean internal queues here, in particular for multilink and
1148 * ppp, and reset HL driver's channel, too. --HE
1149 *
1150 * actually, this may not matter at all, because ISDN hardware
1151 * should not see transmitter hangs at all IMO
Joe Perches475be4d2012-02-19 19:52:38 -08001152 * changed KERN_DEBUG to KERN_WARNING to find out if this is
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 * ever called --KG
1154 */
1155 }
Florian Westphal860e9532016-05-03 16:33:13 +02001156 netif_trans_update(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 netif_wake_queue(ndev);
1158}
1159
1160/*
1161 * Try sending a packet.
1162 * If this interface isn't connected to a ISDN-Channel, find a free channel,
1163 * and start dialing.
1164 */
Stephen Hemminger8b62ff22009-08-31 19:50:44 +00001165static netdev_tx_t
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1167{
Joe Perchesa17531f2010-11-15 11:12:24 +00001168 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001170 struct concap_proto *cprot = lp->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171/* At this point hard_start_xmit() passes control to the encapsulation
1172 protocol (if present).
1173 For X.25 auto-dialing is completly bypassed because:
1174 - It does not conform with the semantics of a reliable datalink
Joe Perches475be4d2012-02-19 19:52:38 -08001175 service as needed by X.25 PLP.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 - I don't want that the interface starts dialing when the network layer
Joe Perches475be4d2012-02-19 19:52:38 -08001177 sends a message which requests to disconnect the lapb link (or if it
1178 sends any other message not resulting in data transmission).
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 Instead, dialing will be initiated by the encapsulation protocol entity
1180 when a dl_establish request is received from the upper layer.
1181*/
Joe Perches475be4d2012-02-19 19:52:38 -08001182 if (cprot && cprot->pops) {
1183 int ret = cprot->pops->encap_and_xmit(cprot, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 if (ret)
1186 netif_stop_queue(ndev);
1187 return ret;
1188 } else
1189#endif
Joe Perches475be4d2012-02-19 19:52:38 -08001190 /* auto-dialing xmit function */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191 {
1192#ifdef ISDN_DEBUG_NET_DUMP
1193 u_char *buf;
1194#endif
1195 isdn_net_adjust_hdr(skb, ndev);
1196#ifdef ISDN_DEBUG_NET_DUMP
1197 buf = skb->data;
1198 isdn_dumppkt("S:", buf, skb->len, 40);
1199#endif
1200
1201 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1202 int chi;
1203 /* only do autodial if allowed by config */
1204 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
1205 isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
1206 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001207 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209 if (lp->phone[1]) {
1210 ulong flags;
1211
Joe Perches475be4d2012-02-19 19:52:38 -08001212 if (lp->dialwait_timer <= 0)
1213 if (lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
1215
Joe Perches475be4d2012-02-19 19:52:38 -08001216 if (lp->dialwait_timer > 0) {
1217 if (time_before(jiffies, lp->dialwait_timer)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
1219 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001220 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 } else
1222 lp->dialwait_timer = 0;
1223 }
1224 /* Grab a free ISDN-Channel */
1225 spin_lock_irqsave(&dev->lock, flags);
1226 if (((chi =
Joe Perches475be4d2012-02-19 19:52:38 -08001227 isdn_get_free_channel(
1228 ISDN_USAGE_NET,
1229 lp->l2_proto,
1230 lp->l3_proto,
1231 lp->pre_device,
1232 lp->pre_channel,
1233 lp->msn)
1234 ) < 0) &&
1235 ((chi =
1236 isdn_get_free_channel(
1237 ISDN_USAGE_NET,
1238 lp->l2_proto,
1239 lp->l3_proto,
1240 lp->pre_device,
1241 lp->pre_channel^1,
1242 lp->msn)
1243 ) < 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 spin_unlock_irqrestore(&dev->lock, flags);
1245 isdn_net_unreachable(ndev, skb,
Joe Perches475be4d2012-02-19 19:52:38 -08001246 "No channel");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001248 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 }
1250 /* Log packet, which triggered dialing */
1251 if (dev->net_verbose)
1252 isdn_net_log_skb(skb, lp);
1253 lp->dialstate = 1;
1254 /* Connect interface with channel */
1255 isdn_net_bind_channel(lp, chi);
1256#ifdef CONFIG_ISDN_PPP
1257 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1258 /* no 'first_skb' handling for syncPPP */
1259 if (isdn_ppp_bind(lp) < 0) {
1260 dev_kfree_skb(skb);
1261 isdn_net_unbind_channel(lp);
1262 spin_unlock_irqrestore(&dev->lock, flags);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001263 return NETDEV_TX_OK; /* STN (skb to nirvana) ;) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 }
1265#ifdef CONFIG_IPPP_FILTER
1266 if (isdn_ppp_autodial_filter(skb, lp)) {
1267 isdn_ppp_free(lp);
1268 isdn_net_unbind_channel(lp);
1269 spin_unlock_irqrestore(&dev->lock, flags);
1270 isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
1271 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001272 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 }
1274#endif
1275 spin_unlock_irqrestore(&dev->lock, flags);
1276 isdn_net_dial(); /* Initiate dialing */
1277 netif_stop_queue(ndev);
Patrick McHardy5b548142009-06-12 06:22:29 +00001278 return NETDEV_TX_BUSY; /* let upper layer requeue skb packet */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 }
1280#endif
1281 /* Initiate dialing */
1282 spin_unlock_irqrestore(&dev->lock, flags);
1283 isdn_net_dial();
1284 isdn_net_device_stop_queue(lp);
Patrick McHardy5b548142009-06-12 06:22:29 +00001285 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 } else {
1287 isdn_net_unreachable(ndev, skb,
1288 "No phone number");
1289 dev_kfree_skb(skb);
Patrick McHardy6ed10652009-06-23 06:03:08 +00001290 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 }
1292 } else {
Joe Perches475be4d2012-02-19 19:52:38 -08001293 /* Device is connected to an ISDN channel */
Florian Westphal860e9532016-05-03 16:33:13 +02001294 netif_trans_update(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 if (!lp->dialstate) {
1296 /* ISDN connection is established, try sending */
1297 int ret;
1298 ret = (isdn_net_xmit(ndev, skb));
Joe Perches475be4d2012-02-19 19:52:38 -08001299 if (ret) netif_stop_queue(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 return ret;
1301 } else
1302 netif_stop_queue(ndev);
1303 }
1304 }
Patrick McHardyd77eeb72009-06-15 23:33:24 +00001305 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306}
1307
1308/*
1309 * Shutdown a net-interface.
1310 */
1311static int
1312isdn_net_close(struct net_device *dev)
1313{
1314 struct net_device *p;
1315#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001316 struct concap_proto *cprot =
1317 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
1318 /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319#endif
1320
1321#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001322 if (cprot && cprot->pops) cprot->pops->close(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323#endif
1324 netif_stop_queue(dev);
Wang Chen838361f2008-12-03 15:49:46 -08001325 p = MASTER_TO_SLAVE(dev);
1326 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 /* If this interface has slaves, stop them also */
1328 while (p) {
1329#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001330 cprot = ((isdn_net_local *)netdev_priv(p))
1331 ->netdev->cprot;
1332 if (cprot && cprot->pops)
1333 cprot->pops->close(cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334#endif
1335 isdn_net_hangup(p);
Wang Chen838361f2008-12-03 15:49:46 -08001336 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337 }
1338 }
1339 isdn_net_hangup(dev);
1340 isdn_unlock_drivers();
1341 return 0;
1342}
1343
1344/*
1345 * Get statistics
1346 */
1347static struct net_device_stats *
1348isdn_net_get_stats(struct net_device *dev)
1349{
Joe Perchesa17531f2010-11-15 11:12:24 +00001350 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 return &lp->stats;
1352}
1353
1354/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
1355 * instead of dev->hard_header_len off. This is done because the
1356 * lowlevel-driver has already pulled off its stuff when we get
1357 * here and this routine only gets called with p_encap == ETHER.
1358 * Determine the packet's protocol ID. The rule here is that we
1359 * assume 802.3 if the type field is short enough to be a length.
1360 * This is normal practice and works for any 'now in use' protocol.
1361 */
1362
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001363static __be16
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
1365{
1366 struct ethhdr *eth;
1367 unsigned char *rawp;
1368
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -07001369 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370 skb_pull(skb, ETH_HLEN);
1371 eth = eth_hdr(skb);
1372
1373 if (*eth->h_dest & 1) {
dingtianhong48f045b2013-12-26 19:41:05 +08001374 if (ether_addr_equal(eth->h_dest, dev->broadcast))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 skb->pkt_type = PACKET_BROADCAST;
1376 else
1377 skb->pkt_type = PACKET_MULTICAST;
1378 }
1379 /*
1380 * This ALLMULTI check should be redundant by 1.4
1381 * so don't forget to remove it.
1382 */
1383
1384 else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
dingtianhong48f045b2013-12-26 19:41:05 +08001385 if (!ether_addr_equal(eth->h_dest, dev->dev_addr))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 skb->pkt_type = PACKET_OTHERHOST;
1387 }
Simon Hormane5c5d222013-03-28 13:38:25 +09001388 if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 return eth->h_proto;
1390
1391 rawp = skb->data;
1392
1393 /*
1394 * This is a magic hack to spot IPX packets. Older Novell breaks
1395 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
1396 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
1397 * won't work for fault tolerant netware but does for the rest.
1398 */
1399 if (*(unsigned short *) rawp == 0xFFFF)
1400 return htons(ETH_P_802_3);
1401 /*
1402 * Real 802.2 LLC
1403 */
1404 return htons(ETH_P_802_2);
1405}
1406
1407
Joe Perches475be4d2012-02-19 19:52:38 -08001408/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 * CISCO HDLC keepalive specific stuff
1410 */
1411static struct sk_buff*
1412isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
1413{
1414 unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
1415 struct sk_buff *skb;
1416
1417 skb = alloc_skb(hl + len, GFP_ATOMIC);
1418 if (skb)
1419 skb_reserve(skb, hl);
Joe Perches475be4d2012-02-19 19:52:38 -08001420 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
1422 return skb;
1423}
1424
1425/* cisco hdlck device private ioctls */
Adrian Bunk3e206b02005-06-25 14:58:35 -07001426static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1428{
Joe Perchesa17531f2010-11-15 11:12:24 +00001429 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 unsigned long len = 0;
1431 unsigned long expires = 0;
1432 int tmp = 0;
1433 int period = lp->cisco_keepalive_period;
1434 s8 debserint = lp->cisco_debserint;
1435 int rc = 0;
1436
1437 if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
1438 return -EINVAL;
1439
1440 switch (cmd) {
1441 /* get/set keepalive period */
Joe Perches475be4d2012-02-19 19:52:38 -08001442 case SIOCGKEEPPERIOD:
1443 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1444 if (copy_to_user(ifr->ifr_data,
1445 &lp->cisco_keepalive_period, len))
1446 rc = -EFAULT;
1447 break;
1448 case SIOCSKEEPPERIOD:
1449 tmp = lp->cisco_keepalive_period;
1450 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1451 if (copy_from_user(&period, ifr->ifr_data, len))
1452 rc = -EFAULT;
1453 if ((period > 0) && (period <= 32767))
1454 lp->cisco_keepalive_period = period;
1455 else
1456 rc = -EINVAL;
1457 if (!rc && (tmp != lp->cisco_keepalive_period)) {
1458 expires = (unsigned long)(jiffies +
1459 lp->cisco_keepalive_period * HZ);
1460 mod_timer(&lp->cisco_timer, expires);
1461 printk(KERN_INFO "%s: Keepalive period set "
1462 "to %d seconds.\n",
1463 dev->name, lp->cisco_keepalive_period);
1464 }
1465 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 /* get/set debugging */
Joe Perches475be4d2012-02-19 19:52:38 -08001468 case SIOCGDEBSERINT:
1469 len = (unsigned long)sizeof(lp->cisco_debserint);
1470 if (copy_to_user(ifr->ifr_data,
1471 &lp->cisco_debserint, len))
1472 rc = -EFAULT;
1473 break;
1474 case SIOCSDEBSERINT:
1475 len = (unsigned long)sizeof(lp->cisco_debserint);
1476 if (copy_from_user(&debserint,
1477 ifr->ifr_data, len))
1478 rc = -EFAULT;
1479 if ((debserint >= 0) && (debserint <= 64))
1480 lp->cisco_debserint = debserint;
1481 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 rc = -EINVAL;
Joe Perches475be4d2012-02-19 19:52:38 -08001483 break;
1484
1485 default:
1486 rc = -EINVAL;
1487 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 }
1489 return (rc);
1490}
1491
Stephen Hemmingerd7005552009-01-07 18:04:17 -08001492
1493static int isdn_net_ioctl(struct net_device *dev,
1494 struct ifreq *ifr, int cmd)
1495{
Joe Perchesa17531f2010-11-15 11:12:24 +00001496 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemmingerd7005552009-01-07 18:04:17 -08001497
1498 switch (lp->p_encap) {
1499#ifdef CONFIG_ISDN_PPP
1500 case ISDN_NET_ENCAP_SYNCPPP:
1501 return isdn_ppp_dev_ioctl(dev, ifr, cmd);
1502#endif
1503 case ISDN_NET_ENCAP_CISCOHDLCK:
1504 return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
1505 default:
1506 return -EINVAL;
1507 }
1508}
1509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510/* called via cisco_timer.function */
1511static void
Kees Cooke99e88a2017-10-16 14:43:17 -07001512isdn_net_ciscohdlck_slarp_send_keepalive(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Kees Cooke99e88a2017-10-16 14:43:17 -07001514 isdn_net_local *lp = from_timer(lp, t, cisco_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 struct sk_buff *skb;
1516 unsigned char *p;
1517 unsigned long last_cisco_myseq = lp->cisco_myseq;
1518 int myseq_diff = 0;
1519
1520 if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
1521 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1522 return;
1523 }
1524 lp->cisco_myseq++;
1525
1526 myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
Joe Perches475be4d2012-02-19 19:52:38 -08001527 if ((lp->cisco_line_state) && ((myseq_diff >= 3) || (myseq_diff <= -3))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 /* line up -> down */
1529 lp->cisco_line_state = 0;
Joe Perches475be4d2012-02-19 19:52:38 -08001530 printk(KERN_WARNING
1531 "UPDOWN: Line protocol on Interface %s,"
1532 " changed state to down\n", lp->netdev->dev->name);
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001533 /* should stop routing higher-level data across */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 } else if ((!lp->cisco_line_state) &&
Joe Perches475be4d2012-02-19 19:52:38 -08001535 (myseq_diff >= 0) && (myseq_diff <= 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 /* line down -> up */
1537 lp->cisco_line_state = 1;
Joe Perches475be4d2012-02-19 19:52:38 -08001538 printk(KERN_WARNING
1539 "UPDOWN: Line protocol on Interface %s,"
1540 " changed state to up\n", lp->netdev->dev->name);
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001541 /* restart routing higher-level data across */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 }
1543
1544 if (lp->cisco_debserint)
Joe Perches475be4d2012-02-19 19:52:38 -08001545 printk(KERN_DEBUG "%s: HDLC "
1546 "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
1547 lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
1548 ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
1549 lp->cisco_yourseq,
1550 ((lp->cisco_line_state) ? "line up" : "line down"));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1553 if (!skb)
1554 return;
1555
1556 p = skb_put(skb, 4 + 14);
1557
1558 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001559 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1560 *(u8 *)(p + 1) = CISCO_CTRL;
1561 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
1563 /* slarp keepalive */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001564 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE);
1565 *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq);
1566 *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq);
Dirk Hohndel06fe9fb2009-09-28 21:43:57 -04001567 *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff
Harvey Harrison00bcd522008-11-13 22:41:29 -08001568 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570 isdn_net_write_super(lp, skb);
1571
1572 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
Joe Perches475be4d2012-02-19 19:52:38 -08001573
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 add_timer(&lp->cisco_timer);
1575}
1576
1577static void
1578isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
1579{
1580 struct sk_buff *skb;
1581 unsigned char *p;
1582
1583 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1584 if (!skb)
1585 return;
1586
1587 p = skb_put(skb, 4 + 14);
1588
1589 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001590 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1591 *(u8 *)(p + 1) = CISCO_CTRL;
1592 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593
1594 /* slarp request */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001595 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REQUEST);
1596 *(__be32 *)(p + 8) = cpu_to_be32(0); // address
1597 *(__be32 *)(p + 12) = cpu_to_be32(0); // netmask
1598 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1599 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
1601 isdn_net_write_super(lp, skb);
1602}
1603
Joe Perches475be4d2012-02-19 19:52:38 -08001604static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605isdn_net_ciscohdlck_connected(isdn_net_local *lp)
1606{
1607 lp->cisco_myseq = 0;
1608 lp->cisco_mineseen = 0;
1609 lp->cisco_yourseq = 0;
1610 lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
1611 lp->cisco_last_slarp_in = 0;
1612 lp->cisco_line_state = 0;
1613 lp->cisco_debserint = 0;
1614
1615 /* send slarp request because interface/seq.no.s reset */
1616 isdn_net_ciscohdlck_slarp_send_request(lp);
1617
Kees Cooke99e88a2017-10-16 14:43:17 -07001618 timer_setup(&lp->cisco_timer,
1619 isdn_net_ciscohdlck_slarp_send_keepalive, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1621 add_timer(&lp->cisco_timer);
1622}
1623
Joe Perches475be4d2012-02-19 19:52:38 -08001624static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
1626{
1627 del_timer(&lp->cisco_timer);
1628}
1629
1630static void
1631isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
1632{
1633 struct sk_buff *skb;
1634 unsigned char *p;
1635 struct in_device *in_dev = NULL;
Al Viroa144ea42006-09-28 18:00:55 -07001636 __be32 addr = 0; /* local ipv4 address */
1637 __be32 mask = 0; /* local netmask */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
Karsten Keild62a38d2007-10-08 20:37:11 -07001639 if ((in_dev = lp->netdev->dev->ip_ptr) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 /* take primary(first) address of interface */
1641 struct in_ifaddr *ifa = in_dev->ifa_list;
1642 if (ifa != NULL) {
1643 addr = ifa->ifa_local;
1644 mask = ifa->ifa_mask;
1645 }
1646 }
1647
1648 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1649 if (!skb)
1650 return;
1651
1652 p = skb_put(skb, 4 + 14);
1653
1654 /* cisco header */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001655 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1656 *(u8 *)(p + 1) = CISCO_CTRL;
1657 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
1659 /* slarp reply, send own ip/netmask; if values are nonsense remote
1660 * should think we are unable to provide it with an address via SLARP */
Harvey Harrison00bcd522008-11-13 22:41:29 -08001661 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REPLY);
David S. Miller198d6ba2008-11-18 23:38:23 -08001662 *(__be32 *)(p + 8) = addr; // address
1663 *(__be32 *)(p + 12) = mask; // netmask
Harvey Harrison00bcd522008-11-13 22:41:29 -08001664 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1665 p += 18;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 isdn_net_write_super(lp, skb);
1668}
1669
1670static void
1671isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
1672{
1673 unsigned char *p;
1674 int period;
1675 u32 code;
Harvey Harrison8cf14e32008-10-29 22:43:33 -07001676 u32 my_seq;
1677 u32 your_seq;
1678 __be32 local;
1679 __be32 *addr, *mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
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;
Joe Perches475be4d2012-02-19 19:52:38 -08001705 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
Joe Perches475be4d2012-02-19 19:52:38 -08001711 + HZ / 2 - 1) / HZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 if (lp->cisco_debserint &&
Joe Perches475be4d2012-02-19 19:52:38 -08001713 (period != lp->cisco_keepalive_period) &&
1714 lp->cisco_last_slarp_in) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 printk(KERN_DEBUG "%s: Keepalive period mismatch - "
Joe Perches475be4d2012-02-19 19:52:38 -08001716 "is %d but should be %d.\n",
1717 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));
Harvey Harrison00bcd522008-11-13 22:41:29 -08001723 p += 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 lp->cisco_yourseq = my_seq;
1725 lp->cisco_mineseen = your_seq;
1726 break;
1727 }
1728}
1729
1730static void
1731isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
1732{
1733 unsigned char *p;
Joe Perches475be4d2012-02-19 19:52:38 -08001734 u8 addr;
1735 u8 ctrl;
1736 u16 type;
1737
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 if (skb->len < 4)
1739 goto out_free;
1740
1741 p = skb->data;
Harvey Harrison00bcd522008-11-13 22:41:29 -08001742 addr = *(u8 *)(p + 0);
1743 ctrl = *(u8 *)(p + 1);
1744 type = be16_to_cpup((__be16 *)(p + 2));
1745 p += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 skb_pull(skb, 4);
Joe Perches475be4d2012-02-19 19:52:38 -08001747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
1749 printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001750 lp->netdev->dev->name, addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 goto out_free;
1752 }
1753 if (ctrl != CISCO_CTRL) {
1754 printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07001755 lp->netdev->dev->name, ctrl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 goto out_free;
1757 }
1758
1759 switch (type) {
1760 case CISCO_TYPE_SLARP:
1761 isdn_net_ciscohdlck_slarp_in(lp, skb);
1762 goto out_free;
1763 case CISCO_TYPE_CDP:
1764 if (lp->cisco_debserint)
1765 printk(KERN_DEBUG "%s: Received CDP packet. use "
Joe Perches475be4d2012-02-19 19:52:38 -08001766 "\"no cdp enable\" on cisco.\n",
1767 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 goto out_free;
1769 default:
1770 /* no special cisco protocol */
1771 skb->protocol = htons(type);
1772 netif_rx(skb);
1773 return;
1774 }
1775
Joe Perches475be4d2012-02-19 19:52:38 -08001776out_free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 kfree_skb(skb);
1778}
1779
1780/*
1781 * Got a packet from ISDN-Channel.
1782 */
1783static void
1784isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
1785{
Joe Perchesa17531f2010-11-15 11:12:24 +00001786 isdn_net_local *lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 isdn_net_local *olp = lp; /* original 'lp' */
1788#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001789 struct concap_proto *cprot = lp->netdev->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790#endif
1791 lp->transcount += skb->len;
1792
1793 lp->stats.rx_packets++;
1794 lp->stats.rx_bytes += skb->len;
1795 if (lp->master) {
1796 /* Bundling: If device is a slave-device, deliver to master, also
1797 * handle master's statistics and hangup-timeout
1798 */
1799 ndev = lp->master;
Joe Perchesa17531f2010-11-15 11:12:24 +00001800 lp = netdev_priv(ndev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 lp->stats.rx_packets++;
1802 lp->stats.rx_bytes += skb->len;
1803 }
1804 skb->dev = ndev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 skb->pkt_type = PACKET_HOST;
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -07001806 skb_reset_mac_header(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807#ifdef ISDN_DEBUG_NET_DUMP
1808 isdn_dumppkt("R:", skb->data, skb->len, 40);
1809#endif
1810 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -08001811 case ISDN_NET_ENCAP_ETHER:
1812 /* Ethernet over ISDN */
1813 olp->huptimer = 0;
1814 lp->huptimer = 0;
1815 skb->protocol = isdn_net_type_trans(skb, ndev);
1816 break;
1817 case ISDN_NET_ENCAP_UIHDLC:
1818 /* HDLC with UI-frame (for ispa with -h1 option) */
1819 olp->huptimer = 0;
1820 lp->huptimer = 0;
1821 skb_pull(skb, 2);
1822 /* Fall through */
1823 case ISDN_NET_ENCAP_RAWIP:
1824 /* RAW-IP without MAC-Header */
1825 olp->huptimer = 0;
1826 lp->huptimer = 0;
1827 skb->protocol = htons(ETH_P_IP);
1828 break;
1829 case ISDN_NET_ENCAP_CISCOHDLCK:
1830 isdn_net_ciscohdlck_receive(lp, skb);
1831 return;
1832 case ISDN_NET_ENCAP_CISCOHDLC:
1833 /* CISCO-HDLC IP with type field and fake I-frame-header */
1834 skb_pull(skb, 2);
1835 /* Fall through */
1836 case ISDN_NET_ENCAP_IPTYP:
1837 /* IP with type field */
1838 olp->huptimer = 0;
1839 lp->huptimer = 0;
1840 skb->protocol = *(__be16 *)&(skb->data[0]);
1841 skb_pull(skb, 2);
1842 if (*(unsigned short *) skb->data == 0xFFFF)
1843 skb->protocol = htons(ETH_P_802_3);
1844 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -08001846 case ISDN_NET_ENCAP_SYNCPPP:
1847 /* huptimer is done in isdn_ppp_push_higher */
1848 isdn_ppp_receive(lp->netdev, olp, skb);
1849 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850#endif
1851
Joe Perches475be4d2012-02-19 19:52:38 -08001852 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08001854 /* try if there are generic sync_device receiver routines */
1855 if (cprot) if (cprot->pops)
1856 if (cprot->pops->data_ind) {
1857 cprot->pops->data_ind(cprot, skb);
1858 return;
1859 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860#endif /* CONFIG_ISDN_X25 */
Joe Perches475be4d2012-02-19 19:52:38 -08001861 printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
1862 lp->netdev->dev->name);
1863 kfree_skb(skb);
1864 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865 }
1866
1867 netif_rx(skb);
1868 return;
1869}
1870
1871/*
1872 * A packet arrived via ISDN. Search interface-chain for a corresponding
1873 * interface. If found, deliver packet to receiver-function and return 1,
1874 * else return 0.
1875 */
1876int
1877isdn_net_rcv_skb(int idx, struct sk_buff *skb)
1878{
1879 isdn_net_dev *p = dev->rx_netdev[idx];
1880
1881 if (p) {
1882 isdn_net_local *lp = p->local;
1883 if ((lp->flags & ISDN_NET_CONNECTED) &&
1884 (!lp->dialstate)) {
Karsten Keild62a38d2007-10-08 20:37:11 -07001885 isdn_net_receive(p->dev, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 return 1;
1887 }
1888 }
1889 return 0;
1890}
1891
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892/*
1893 * build an header
1894 * depends on encaps that is being used.
1895 */
1896
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001897static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
1898 unsigned short type,
1899 const void *daddr, const void *saddr, unsigned plen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900{
Wang Chen838361f2008-12-03 15:49:46 -08001901 isdn_net_local *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902 unsigned char *p;
Dan Carpenter5a46e0f2012-02-09 00:46:47 +00001903 int len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001904
1905 switch (lp->p_encap) {
Joe Perches475be4d2012-02-19 19:52:38 -08001906 case ISDN_NET_ENCAP_ETHER:
1907 len = eth_header(skb, dev, type, daddr, saddr, plen);
1908 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001909#ifdef CONFIG_ISDN_PPP
Joe Perches475be4d2012-02-19 19:52:38 -08001910 case ISDN_NET_ENCAP_SYNCPPP:
1911 /* stick on a fake header to keep fragmentation code happy. */
1912 len = IPPP_MAX_HEADER;
1913 skb_push(skb, len);
1914 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915#endif
Joe Perches475be4d2012-02-19 19:52:38 -08001916 case ISDN_NET_ENCAP_RAWIP:
1917 printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
1918 len = 0;
1919 break;
1920 case ISDN_NET_ENCAP_IPTYP:
1921 /* ethernet type field */
1922 *((__be16 *)skb_push(skb, 2)) = htons(type);
1923 len = 2;
1924 break;
1925 case ISDN_NET_ENCAP_UIHDLC:
1926 /* HDLC with UI-Frames (for ispa with -h1 option) */
1927 *((__be16 *)skb_push(skb, 2)) = htons(0x0103);
1928 len = 2;
1929 break;
1930 case ISDN_NET_ENCAP_CISCOHDLC:
1931 case ISDN_NET_ENCAP_CISCOHDLCK:
1932 p = skb_push(skb, 4);
1933 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1934 *(u8 *)(p + 1) = CISCO_CTRL;
1935 *(__be16 *)(p + 2) = cpu_to_be16(type);
1936 p += 4;
1937 len = 4;
1938 break;
1939#ifdef CONFIG_ISDN_X25
1940 default:
1941 /* try if there are generic concap protocol routines */
1942 if (lp->netdev->cprot) {
1943 printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 len = 0;
1945 break;
Joe Perches475be4d2012-02-19 19:52:38 -08001946 }
1947 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948#endif /* CONFIG_ISDN_X25 */
1949 }
1950 return len;
1951}
1952
David S. Millere69dd332011-07-12 23:28:12 -07001953static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
1954 __be16 type)
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001955{
1956 const struct net_device *dev = neigh->dev;
Wang Chen838361f2008-12-03 15:49:46 -08001957 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001958
1959 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
David S. Millere69dd332011-07-12 23:28:12 -07001960 return eth_header_cache(neigh, hh, type);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001961 return -1;
1962}
1963
1964static void isdn_header_cache_update(struct hh_cache *hh,
1965 const struct net_device *dev,
1966 const unsigned char *haddr)
1967{
Wang Chen838361f2008-12-03 15:49:46 -08001968 isdn_net_local *lp = netdev_priv(dev);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001969 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
Harvey Harrisonc19d0362008-11-20 04:10:51 -08001970 eth_header_cache_update(hh, dev, haddr);
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001971}
1972
1973static const struct header_ops isdn_header_ops = {
1974 .create = isdn_net_header,
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001975 .cache = isdn_header_cache,
1976 .cache_update = isdn_header_cache_update,
1977};
1978
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979/*
1980 * Interface-setup. (just after registering a new interface)
1981 */
1982static int
1983isdn_net_init(struct net_device *ndev)
1984{
1985 ushort max_hlhdr_len = 0;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001986 int drvidx;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001987
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 /*
1989 * up till binding we ask the protocol layer to reserve as much
1990 * as we might need for HL layer
1991 */
1992
1993 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
1994 if (dev->drv[drvidx])
1995 if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
1996 max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
1997
1998 ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999 return 0;
2000}
2001
2002static void
2003isdn_net_swapbind(int drvidx)
2004{
2005 isdn_net_dev *p;
2006
2007#ifdef ISDN_DEBUG_NET_ICALL
2008 printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
2009#endif
2010 p = dev->netdev;
2011 while (p) {
2012 if (p->local->pre_device == drvidx)
2013 switch (p->local->pre_channel) {
Joe Perches475be4d2012-02-19 19:52:38 -08002014 case 0:
2015 p->local->pre_channel = 1;
2016 break;
2017 case 1:
2018 p->local->pre_channel = 0;
2019 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020 }
2021 p = (isdn_net_dev *) p->next;
2022 }
2023}
2024
2025static void
2026isdn_net_swap_usage(int i1, int i2)
2027{
2028 int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
2029 int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
2030
2031#ifdef ISDN_DEBUG_NET_ICALL
2032 printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
2033#endif
2034 dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
2035 dev->usage[i1] |= u2;
2036 dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
2037 dev->usage[i2] |= u1;
2038 isdn_info_update();
2039}
2040
2041/*
2042 * An incoming call-request has arrived.
2043 * Search the interface-chain for an appropriate interface.
2044 * If found, connect the interface to the ISDN-channel and initiate
2045 * D- and B-Channel-setup. If secure-flag is set, accept only
2046 * configured phone-numbers. If callback-flag is set, initiate
2047 * callback-dialing.
2048 *
2049 * Return-Value: 0 = No appropriate interface for this call.
2050 * 1 = Call accepted
2051 * 2 = Reject call, wait cbdelay, then call back
2052 * 3 = Reject call
2053 * 4 = Wait cbdelay, then call back
2054 * 5 = No appropriate interface for this call,
2055 * would eventually match if CID was longer.
2056 */
2057
2058int
2059isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
2060{
2061 char *eaz;
2062 int si1;
2063 int si2;
2064 int ematch;
2065 int wret;
2066 int swapped;
2067 int sidx = 0;
2068 u_long flags;
2069 isdn_net_dev *p;
2070 isdn_net_phone *n;
Karsten Keil0f138642007-11-22 12:43:13 +01002071 char nr[ISDN_MSNLEN];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072 char *my_eaz;
2073
2074 /* Search name in netdev-chain */
2075 if (!setup->phone[0]) {
2076 nr[0] = '0';
2077 nr[1] = '\0';
2078 printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
2079 } else
Karsten Keil0f138642007-11-22 12:43:13 +01002080 strlcpy(nr, setup->phone, ISDN_MSNLEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081 si1 = (int) setup->si1;
2082 si2 = (int) setup->si2;
2083 if (!setup->eazmsn[0]) {
2084 printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
2085 eaz = "0";
2086 } else
2087 eaz = setup->eazmsn;
2088 if (dev->net_verbose > 1)
2089 printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
2090 /* Accept DATA and VOICE calls at this stage
2091 * local eaz is checked later for allowed call types
2092 */
2093 if ((si1 != 7) && (si1 != 1)) {
2094 if (dev->net_verbose > 1)
2095 printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
2096 return 0;
2097 }
2098 n = (isdn_net_phone *) 0;
2099 p = dev->netdev;
2100 ematch = wret = swapped = 0;
2101#ifdef ISDN_DEBUG_NET_ICALL
2102 printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
Joe Perches475be4d2012-02-19 19:52:38 -08002103 dev->usage[idx]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104#endif
2105 while (p) {
2106 int matchret;
2107 isdn_net_local *lp = p->local;
2108
2109 /* If last check has triggered as binding-swap, revert it */
2110 switch (swapped) {
Joe Perches475be4d2012-02-19 19:52:38 -08002111 case 2:
2112 isdn_net_swap_usage(idx, sidx);
2113 /* fall through */
2114 case 1:
2115 isdn_net_swapbind(di);
2116 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117 }
2118 swapped = 0;
Joe Perches475be4d2012-02-19 19:52:38 -08002119 /* check acceptable call types for DOV */
2120 my_eaz = isdn_map_eaz2msn(lp->msn, di);
2121 if (si1 == 1) { /* it's a DOV call, check if we allow it */
2122 if (*my_eaz == 'v' || *my_eaz == 'V' ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 *my_eaz == 'b' || *my_eaz == 'B')
Joe Perches475be4d2012-02-19 19:52:38 -08002124 my_eaz++; /* skip to allow a match */
2125 else
2126 my_eaz = NULL; /* force non match */
2127 } else { /* it's a DATA call, check if we allow it */
2128 if (*my_eaz == 'b' || *my_eaz == 'B')
2129 my_eaz++; /* skip to allow a match */
2130 }
2131 if (my_eaz)
2132 matchret = isdn_msncmp(eaz, my_eaz);
2133 else
2134 matchret = 1;
2135 if (!matchret)
2136 ematch = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
2138 /* Remember if more numbers eventually can match */
2139 if (matchret > wret)
2140 wret = matchret;
2141#ifdef ISDN_DEBUG_NET_ICALL
2142 printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002143 p->dev->name, lp->msn, lp->flags, lp->dialstate);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144#endif
2145 if ((!matchret) && /* EAZ is matching */
2146 (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
2147 (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
2148 ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
2149 (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
Joe Perches475be4d2012-02-19 19:52:38 -08002150 )))
2151 {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152#ifdef ISDN_DEBUG_NET_ICALL
2153 printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
2154 lp->pre_device, lp->pre_channel);
2155#endif
2156 if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
2157 if ((lp->pre_channel != ch) ||
2158 (lp->pre_device != di)) {
2159 /* Here we got a problem:
2160 * If using an ICN-Card, an incoming call is always signaled on
2161 * on the first channel of the card, if both channels are
2162 * down. However this channel may be bound exclusive. If the
2163 * second channel is free, this call should be accepted.
2164 * The solution is horribly but it runs, so what:
2165 * We exchange the exclusive bindings of the two channels, the
2166 * corresponding variables in the interface-structs.
2167 */
2168 if (ch == 0) {
2169 sidx = isdn_dc2minor(di, 1);
2170#ifdef ISDN_DEBUG_NET_ICALL
2171 printk(KERN_DEBUG "n_fi: ch is 0\n");
2172#endif
2173 if (USG_NONE(dev->usage[sidx])) {
2174 /* Second Channel is free, now see if it is bound
2175 * exclusive too. */
2176 if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
2177#ifdef ISDN_DEBUG_NET_ICALL
2178 printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
2179#endif
2180 /* Yes, swap bindings only, if the original
2181 * binding is bound to channel 1 of this driver */
2182 if ((lp->pre_device == di) &&
2183 (lp->pre_channel == 1)) {
2184 isdn_net_swapbind(di);
2185 swapped = 1;
2186 } else {
2187 /* ... else iterate next device */
2188 p = (isdn_net_dev *) p->next;
2189 continue;
2190 }
2191 } else {
2192#ifdef ISDN_DEBUG_NET_ICALL
2193 printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
2194#endif
2195 /* No, swap always and swap excl-usage also */
2196 isdn_net_swap_usage(idx, sidx);
2197 isdn_net_swapbind(di);
2198 swapped = 2;
2199 }
2200 /* Now check for exclusive binding again */
2201#ifdef ISDN_DEBUG_NET_ICALL
2202 printk(KERN_DEBUG "n_fi: final check\n");
2203#endif
2204 if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
2205 ((lp->pre_channel != ch) ||
2206 (lp->pre_device != di))) {
2207#ifdef ISDN_DEBUG_NET_ICALL
2208 printk(KERN_DEBUG "n_fi: final check failed\n");
2209#endif
2210 p = (isdn_net_dev *) p->next;
2211 continue;
2212 }
2213 }
2214 } else {
2215 /* We are already on the second channel, so nothing to do */
2216#ifdef ISDN_DEBUG_NET_ICALL
2217 printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
2218#endif
2219 }
2220 }
2221 }
2222#ifdef ISDN_DEBUG_NET_ICALL
2223 printk(KERN_DEBUG "n_fi: match2\n");
2224#endif
2225 n = lp->phone[0];
2226 if (lp->flags & ISDN_NET_SECURE) {
2227 while (n) {
2228 if (!isdn_msncmp(nr, n->num))
2229 break;
2230 n = (isdn_net_phone *) n->next;
2231 }
2232 }
2233 if (n || (!(lp->flags & ISDN_NET_SECURE))) {
2234#ifdef ISDN_DEBUG_NET_ICALL
2235 printk(KERN_DEBUG "n_fi: match3\n");
2236#endif
2237 /* matching interface found */
2238
2239 /*
2240 * Is the state STOPPED?
2241 * If so, no dialin is allowed,
2242 * so reject actively.
2243 * */
2244 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2245 printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002246 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 return 3;
2248 }
2249 /*
2250 * Is the interface up?
2251 * If not, reject the call actively.
2252 */
2253 if (!isdn_net_device_started(p)) {
2254 printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002255 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 return 3;
2257 }
2258 /* Interface is up, now see if it's a slave. If so, see if
2259 * it's master and parent slave is online. If not, reject the call.
2260 */
2261 if (lp->master) {
Wang Chen838361f2008-12-03 15:49:46 -08002262 isdn_net_local *mlp = ISDN_MASTER_PRIV(lp);
Karsten Keilfaca94f2007-10-15 02:11:44 -07002263 printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
2264 printk(KERN_DEBUG "master=%s\n", lp->master->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 if (mlp->flags & ISDN_NET_CONNECTED) {
2266 printk(KERN_DEBUG "master online\n");
2267 /* Master is online, find parent-slave (master if first slave) */
2268 while (mlp->slave) {
Wang Chen838361f2008-12-03 15:49:46 -08002269 if (ISDN_SLAVE_PRIV(mlp) == lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 break;
Wang Chen838361f2008-12-03 15:49:46 -08002271 mlp = ISDN_SLAVE_PRIV(mlp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 }
2273 } else
2274 printk(KERN_DEBUG "master offline\n");
2275 /* Found parent, if it's offline iterate next device */
2276 printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
2277 if (!(mlp->flags & ISDN_NET_CONNECTED)) {
2278 p = (isdn_net_dev *) p->next;
2279 continue;
2280 }
Joe Perches475be4d2012-02-19 19:52:38 -08002281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 if (lp->flags & ISDN_NET_CALLBACK) {
2283 int chi;
2284 /*
2285 * Is the state MANUAL?
2286 * If so, no callback can be made,
2287 * so reject actively.
2288 * */
2289 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2290 printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002291 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 return 3;
2293 }
2294 printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002295 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 if (lp->phone[1]) {
2297 /* Grab a free ISDN-Channel */
2298 spin_lock_irqsave(&dev->lock, flags);
Joe Perches475be4d2012-02-19 19:52:38 -08002299 if ((chi =
2300 isdn_get_free_channel(
2301 ISDN_USAGE_NET,
2302 lp->l2_proto,
2303 lp->l3_proto,
2304 lp->pre_device,
2305 lp->pre_channel,
2306 lp->msn)
2307 ) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Karsten Keilfaca94f2007-10-15 02:11:44 -07002309 printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002310 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 spin_unlock_irqrestore(&dev->lock, flags);
2312 return 0;
2313 }
2314 /* Setup dialstate. */
2315 lp->dtimer = 0;
2316 lp->dialstate = 11;
2317 /* Connect interface with channel */
2318 isdn_net_bind_channel(lp, chi);
2319#ifdef CONFIG_ISDN_PPP
2320 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2321 if (isdn_ppp_bind(lp) < 0) {
2322 spin_unlock_irqrestore(&dev->lock, flags);
2323 isdn_net_unbind_channel(lp);
2324 return 0;
2325 }
2326#endif
2327 spin_unlock_irqrestore(&dev->lock, flags);
2328 /* Initiate dialing by returning 2 or 4 */
2329 return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
2330 } else
Karsten Keilfaca94f2007-10-15 02:11:44 -07002331 printk(KERN_WARNING "isdn_net: %s: No phone number\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002332 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 return 0;
2334 } else {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002335 printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002336 p->dev->name, nr, eaz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337 /* if this interface is dialing, it does it probably on a different
2338 device, so free this device */
2339 if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
2340#ifdef CONFIG_ISDN_PPP
2341 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2342 isdn_ppp_free(lp);
2343#endif
2344 isdn_net_lp_disconnected(lp);
2345 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
Joe Perches475be4d2012-02-19 19:52:38 -08002346 ISDN_USAGE_NET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 }
2348 spin_lock_irqsave(&dev->lock, flags);
2349 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2350 dev->usage[idx] |= ISDN_USAGE_NET;
2351 strcpy(dev->num[idx], nr);
2352 isdn_info_update();
2353 dev->st_netdev[idx] = lp->netdev;
2354 lp->isdn_device = di;
2355 lp->isdn_channel = ch;
2356 lp->ppp_slot = -1;
2357 lp->flags |= ISDN_NET_CONNECTED;
2358 lp->dialstate = 7;
2359 lp->dtimer = 0;
2360 lp->outgoing = 0;
2361 lp->huptimer = 0;
2362 lp->hupflags |= ISDN_WAITCHARGE;
2363 lp->hupflags &= ~ISDN_HAVECHARGE;
2364#ifdef CONFIG_ISDN_PPP
2365 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
2366 if (isdn_ppp_bind(lp) < 0) {
2367 isdn_net_unbind_channel(lp);
2368 spin_unlock_irqrestore(&dev->lock, flags);
2369 return 0;
2370 }
2371 }
2372#endif
2373 spin_unlock_irqrestore(&dev->lock, flags);
2374 return 1;
2375 }
2376 }
2377 }
2378 p = (isdn_net_dev *) p->next;
2379 }
2380 /* If none of configured EAZ/MSN matched and not verbose, be silent */
2381 if (!ematch || dev->net_verbose)
2382 printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
Joe Perches475be4d2012-02-19 19:52:38 -08002383 return (wret == 2) ? 5 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384}
2385
2386/*
2387 * Search list of net-interfaces for an interface with given name.
2388 */
2389isdn_net_dev *
2390isdn_net_findif(char *name)
2391{
2392 isdn_net_dev *p = dev->netdev;
2393
2394 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002395 if (!strcmp(p->dev->name, name))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396 return p;
2397 p = (isdn_net_dev *) p->next;
2398 }
2399 return (isdn_net_dev *) NULL;
2400}
2401
2402/*
2403 * Force a net-interface to dial out.
2404 * This is called from the userlevel-routine below or
2405 * from isdn_net_start_xmit().
2406 */
Adrian Bunk3e206b02005-06-25 14:58:35 -07002407static int
Joe Perches475be4d2012-02-19 19:52:38 -08002408isdn_net_force_dial_lp(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409{
2410 if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
2411 int chi;
2412 if (lp->phone[1]) {
2413 ulong flags;
2414
2415 /* Grab a free ISDN-Channel */
2416 spin_lock_irqsave(&dev->lock, flags);
2417 if ((chi = isdn_get_free_channel(
Joe Perches475be4d2012-02-19 19:52:38 -08002418 ISDN_USAGE_NET,
2419 lp->l2_proto,
2420 lp->l3_proto,
2421 lp->pre_device,
2422 lp->pre_channel,
2423 lp->msn)) < 0) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07002424 printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
Joe Perches475be4d2012-02-19 19:52:38 -08002425 lp->netdev->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426 spin_unlock_irqrestore(&dev->lock, flags);
2427 return -EAGAIN;
2428 }
2429 lp->dialstate = 1;
2430 /* Connect interface with channel */
2431 isdn_net_bind_channel(lp, chi);
2432#ifdef CONFIG_ISDN_PPP
2433 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2434 if (isdn_ppp_bind(lp) < 0) {
2435 isdn_net_unbind_channel(lp);
2436 spin_unlock_irqrestore(&dev->lock, flags);
2437 return -EAGAIN;
2438 }
2439#endif
2440 /* Initiate dialing */
2441 spin_unlock_irqrestore(&dev->lock, flags);
2442 isdn_net_dial();
2443 return 0;
2444 } else
2445 return -EINVAL;
2446 } else
2447 return -EBUSY;
2448}
2449
2450/*
2451 * This is called from certain upper protocol layers (multilink ppp
2452 * and x25iface encapsulation module) that want to initiate dialing
2453 * themselves.
2454 */
2455int
Joe Perches475be4d2012-02-19 19:52:38 -08002456isdn_net_dial_req(isdn_net_local *lp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457{
2458 /* is there a better error code? */
2459 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
2460
2461 return isdn_net_force_dial_lp(lp);
2462}
2463
2464/*
2465 * Force a net-interface to dial out.
2466 * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
2467 */
2468int
2469isdn_net_force_dial(char *name)
2470{
2471 isdn_net_dev *p = isdn_net_findif(name);
2472
2473 if (!p)
2474 return -ENODEV;
2475 return (isdn_net_force_dial_lp(p->local));
2476}
2477
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002478/* The ISDN-specific entries in the device structure. */
2479static const struct net_device_ops isdn_netdev_ops = {
2480 .ndo_init = isdn_net_init,
2481 .ndo_open = isdn_net_open,
2482 .ndo_stop = isdn_net_close,
2483 .ndo_do_ioctl = isdn_net_ioctl,
2484
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002485 .ndo_start_xmit = isdn_net_start_xmit,
2486 .ndo_get_stats = isdn_net_get_stats,
2487 .ndo_tx_timeout = isdn_net_tx_timeout,
2488};
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490/*
Karsten Keild62a38d2007-10-08 20:37:11 -07002491 * Helper for alloc_netdev()
2492 */
2493static void _isdn_setup(struct net_device *dev)
2494{
Wang Chen838361f2008-12-03 15:49:46 -08002495 isdn_net_local *lp = netdev_priv(dev);
Karsten Keild62a38d2007-10-08 20:37:11 -07002496
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002497 ether_setup(dev);
2498
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002499 /* Setup the generic properties */
Joe Perches475be4d2012-02-19 19:52:38 -08002500 dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Neil Horman550fd082011-07-26 06:05:38 +00002501
2502 /* isdn prepends a header in the tx path, can't share skbs */
2503 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002504 dev->header_ops = NULL;
2505 dev->netdev_ops = &isdn_netdev_ops;
2506
2507 /* for clients with MPPP maybe higher values better */
2508 dev->tx_queue_len = 30;
2509
Karsten Keild62a38d2007-10-08 20:37:11 -07002510 lp->p_encap = ISDN_NET_ENCAP_RAWIP;
2511 lp->magic = ISDN_NET_MAGIC;
2512 lp->last = lp;
2513 lp->next = lp;
2514 lp->isdn_device = -1;
2515 lp->isdn_channel = -1;
2516 lp->pre_device = -1;
2517 lp->pre_channel = -1;
2518 lp->exclusive = -1;
2519 lp->ppp_slot = -1;
2520 lp->pppbind = -1;
2521 skb_queue_head_init(&lp->super_tx_queue);
2522 lp->l2_proto = ISDN_PROTO_L2_X75I;
2523 lp->l3_proto = ISDN_PROTO_L3_TRANS;
2524 lp->triggercps = 6000;
2525 lp->slavedelay = 10 * HZ;
2526 lp->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
2527 lp->onhtime = 10; /* Default hangup-time for saving costs */
2528 lp->dialmax = 1;
2529 /* Hangup before Callback, manual dial */
2530 lp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
2531 lp->cbdelay = 25; /* Wait 5 secs before Callback */
2532 lp->dialtimeout = -1; /* Infinite Dial-Timeout */
2533 lp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
2534 lp->dialstarted = 0; /* Jiffies of last dial-start */
2535 lp->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
2536}
2537
2538/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539 * Allocate a new network-interface and initialize its data structures.
2540 */
2541char *
2542isdn_net_new(char *name, struct net_device *master)
2543{
2544 isdn_net_dev *netdev;
2545
2546 /* Avoid creating an existing interface */
2547 if (isdn_net_findif(name)) {
2548 printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
2549 return NULL;
2550 }
Karsten Keild62a38d2007-10-08 20:37:11 -07002551 if (name == NULL)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002552 return NULL;
Burman Yan41f96932006-12-08 02:39:35 -08002553 if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
2555 return NULL;
2556 }
Tom Gundersenc835a672014-07-14 16:37:24 +02002557 netdev->dev = alloc_netdev(sizeof(isdn_net_local), name,
2558 NET_NAME_UNKNOWN, _isdn_setup);
Karsten Keild62a38d2007-10-08 20:37:11 -07002559 if (!netdev->dev) {
2560 printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 kfree(netdev);
2562 return NULL;
2563 }
Wang Chen838361f2008-12-03 15:49:46 -08002564 netdev->local = netdev_priv(netdev->dev);
Stephen Hemmingerd7005552009-01-07 18:04:17 -08002565
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (master) {
2567 /* Device shall be a slave */
Wang Chen838361f2008-12-03 15:49:46 -08002568 struct net_device *p = MASTER_TO_SLAVE(master);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 struct net_device *q = master;
2570
2571 netdev->local->master = master;
2572 /* Put device at end of slave-chain */
2573 while (p) {
2574 q = p;
Wang Chen838361f2008-12-03 15:49:46 -08002575 p = MASTER_TO_SLAVE(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576 }
Wang Chen838361f2008-12-03 15:49:46 -08002577 MASTER_TO_SLAVE(q) = netdev->dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 } else {
2579 /* Device shall be a master */
2580 /*
2581 * Watchdog timer (currently) for master only.
2582 */
Karsten Keild62a38d2007-10-08 20:37:11 -07002583 netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
2584 if (register_netdev(netdev->dev) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 printk(KERN_WARNING "isdn_net: Could not register net-device\n");
Karsten Keild62a38d2007-10-08 20:37:11 -07002586 free_netdev(netdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 kfree(netdev);
2588 return NULL;
2589 }
2590 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 netdev->queue = netdev->local;
2592 spin_lock_init(&netdev->queue_lock);
2593
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 netdev->local->netdev = netdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
David Howellsc4028952006-11-22 14:57:56 +00002596 INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597 spin_lock_init(&netdev->local->xmit_lock);
2598
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 /* Put into to netdev-chain */
2600 netdev->next = (void *) dev->netdev;
2601 dev->netdev = netdev;
Karsten Keild62a38d2007-10-08 20:37:11 -07002602 return netdev->dev->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603}
2604
2605char *
2606isdn_net_newslave(char *parm)
2607{
2608 char *p = strchr(parm, ',');
2609 isdn_net_dev *n;
2610 char newname[10];
2611
2612 if (p) {
Annie Cherkaev9f5af542017-07-15 15:08:58 -06002613 /* Slave-Name MUST not be empty or overflow 'newname' */
2614 if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 *p = 0;
2617 /* Master must already exist */
2618 if (!(n = isdn_net_findif(parm)))
2619 return NULL;
2620 /* Master must be a real interface, not a slave */
2621 if (n->local->master)
2622 return NULL;
2623 /* Master must not be started yet */
Joe Perches475be4d2012-02-19 19:52:38 -08002624 if (isdn_net_device_started(n))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 return NULL;
Karsten Keild62a38d2007-10-08 20:37:11 -07002626 return (isdn_net_new(newname, n->dev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 }
2628 return NULL;
2629}
2630
2631/*
2632 * Set interface-parameters.
2633 * Always set all parameters, so the user-level application is responsible
2634 * for not overwriting existing setups. It has to get the current
2635 * setup first, if only selected parameters are to be changed.
2636 */
2637int
Joe Perches475be4d2012-02-19 19:52:38 -08002638isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639{
2640 isdn_net_dev *p = isdn_net_findif(cfg->name);
2641 ulong features;
2642 int i;
2643 int drvidx;
2644 int chidx;
2645 char drvid[25];
2646
2647 if (p) {
2648 isdn_net_local *lp = p->local;
2649
2650 /* See if any registered driver supports the features we want */
2651 features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
2652 ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
2653 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2654 if (dev->drv[i])
2655 if ((dev->drv[i]->interface->features & features) == features)
2656 break;
2657 if (i == ISDN_MAX_DRIVERS) {
2658 printk(KERN_WARNING "isdn_net: No driver with selected features\n");
2659 return -ENODEV;
2660 }
Joe Perches475be4d2012-02-19 19:52:38 -08002661 if (lp->p_encap != cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08002663 struct concap_proto *cprot = p->cprot;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664#endif
2665 if (isdn_net_device_started(p)) {
2666 printk(KERN_WARNING "%s: cannot change encap when if is up\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002667 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 return -EBUSY;
2669 }
2670#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08002671 if (cprot && cprot->pops)
2672 cprot->pops->proto_del(cprot);
2673 p->cprot = NULL;
2674 lp->dops = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 /* ... , prepare for configuration of new one ... */
Joe Perches475be4d2012-02-19 19:52:38 -08002676 switch (cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 case ISDN_NET_ENCAP_X25IFACE:
Joe Perches475be4d2012-02-19 19:52:38 -08002678 lp->dops = &isdn_concap_reliable_dl_dops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 }
2680 /* ... and allocate new one ... */
Joe Perches475be4d2012-02-19 19:52:38 -08002681 p->cprot = isdn_concap_new(cfg->p_encap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 /* p -> cprot == NULL now if p_encap is not supported
2683 by means of the concap_proto mechanism */
2684 /* the protocol is not configured yet; this will
2685 happen later when isdn_net_reset() is called */
2686#endif
2687 }
Joe Perches475be4d2012-02-19 19:52:38 -08002688 switch (cfg->p_encap) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 case ISDN_NET_ENCAP_SYNCPPP:
2690#ifndef CONFIG_ISDN_PPP
2691 printk(KERN_WARNING "%s: SyncPPP support not configured\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002692 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 return -EINVAL;
2694#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002695 p->dev->type = ARPHRD_PPP; /* change ARP type */
2696 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697#endif
2698 break;
2699 case ISDN_NET_ENCAP_X25IFACE:
2700#ifndef CONFIG_ISDN_X25
2701 printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
Denis V. Lunevc749b012007-10-15 12:52:20 -07002702 p->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 return -EINVAL;
2704#else
Karsten Keild62a38d2007-10-08 20:37:11 -07002705 p->dev->type = ARPHRD_X25; /* change ARP type */
2706 p->dev->addr_len = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707#endif
2708 break;
2709 case ISDN_NET_ENCAP_CISCOHDLCK:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 break;
2711 default:
Joe Perches475be4d2012-02-19 19:52:38 -08002712 if (cfg->p_encap >= 0 &&
2713 cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 break;
2715 printk(KERN_WARNING
2716 "%s: encapsulation protocol %d not supported\n",
Karsten Keilfaca94f2007-10-15 02:11:44 -07002717 p->dev->name, cfg->p_encap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 return -EINVAL;
2719 }
2720 if (strlen(cfg->drvid)) {
2721 /* A bind has been requested ... */
2722 char *c,
Joe Perches475be4d2012-02-19 19:52:38 -08002723 *e;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724
Dan Carpenter5dc55032011-11-24 02:42:09 +00002725 if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
Joe Perches475be4d2012-02-19 19:52:38 -08002726 sizeof(cfg->drvid))
Dan Carpenter5dc55032011-11-24 02:42:09 +00002727 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 drvidx = -1;
2729 chidx = -1;
2730 strcpy(drvid, cfg->drvid);
2731 if ((c = strchr(drvid, ','))) {
2732 /* The channel-number is appended to the driver-Id with a comma */
2733 chidx = (int) simple_strtoul(c + 1, &e, 10);
2734 if (e == c)
2735 chidx = -1;
2736 *c = '\0';
2737 }
2738 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2739 /* Lookup driver-Id in array */
2740 if (!(strcmp(dev->drvid[i], drvid))) {
2741 drvidx = i;
2742 break;
2743 }
2744 if ((drvidx == -1) || (chidx == -1))
2745 /* Either driver-Id or channel-number invalid */
2746 return -ENODEV;
2747 } else {
2748 /* Parameters are valid, so get them */
2749 drvidx = lp->pre_device;
2750 chidx = lp->pre_channel;
2751 }
2752 if (cfg->exclusive > 0) {
2753 unsigned long flags;
2754
2755 /* If binding is exclusive, try to grab the channel */
2756 spin_lock_irqsave(&dev->lock, flags);
2757 if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
Joe Perches475be4d2012-02-19 19:52:38 -08002758 lp->l2_proto, lp->l3_proto, drvidx,
2759 chidx, lp->msn)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 /* Grab failed, because desired channel is in use */
2761 lp->exclusive = -1;
2762 spin_unlock_irqrestore(&dev->lock, flags);
2763 return -EBUSY;
2764 }
2765 /* All went ok, so update isdninfo */
2766 dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2767 isdn_info_update();
2768 spin_unlock_irqrestore(&dev->lock, flags);
2769 lp->exclusive = i;
2770 } else {
2771 /* Non-exclusive binding or unbind. */
2772 lp->exclusive = -1;
2773 if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2774 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2775 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2776 drvidx = -1;
2777 chidx = -1;
2778 }
2779 }
Karsten Keil0f138642007-11-22 12:43:13 +01002780 strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 lp->pre_device = drvidx;
2782 lp->pre_channel = chidx;
2783 lp->onhtime = cfg->onhtime;
2784 lp->charge = cfg->charge;
2785 lp->l2_proto = cfg->l2_proto;
2786 lp->l3_proto = cfg->l3_proto;
2787 lp->cbdelay = cfg->cbdelay;
2788 lp->dialmax = cfg->dialmax;
2789 lp->triggercps = cfg->triggercps;
2790 lp->slavedelay = cfg->slavedelay * HZ;
2791 lp->pppbind = cfg->pppbind;
2792 lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
2793 lp->dialwait = cfg->dialwait * HZ;
2794 if (cfg->secure)
2795 lp->flags |= ISDN_NET_SECURE;
2796 else
2797 lp->flags &= ~ISDN_NET_SECURE;
2798 if (cfg->cbhup)
2799 lp->flags |= ISDN_NET_CBHUP;
2800 else
2801 lp->flags &= ~ISDN_NET_CBHUP;
2802 switch (cfg->callback) {
Joe Perches475be4d2012-02-19 19:52:38 -08002803 case 0:
2804 lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
2805 break;
2806 case 1:
2807 lp->flags |= ISDN_NET_CALLBACK;
2808 lp->flags &= ~ISDN_NET_CBOUT;
2809 break;
2810 case 2:
2811 lp->flags |= ISDN_NET_CBOUT;
2812 lp->flags &= ~ISDN_NET_CALLBACK;
2813 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 }
2815 lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
2816 if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
2817 /* old isdnctrl version, where only 0 or 1 is given */
2818 printk(KERN_WARNING
Joe Perches475be4d2012-02-19 19:52:38 -08002819 "Old isdnctrl version detected! Please update.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
2821 }
2822 else {
2823 lp->flags |= cfg->dialmode; /* turn on selected bits */
2824 }
2825 if (cfg->chargehup)
2826 lp->hupflags |= ISDN_CHARGEHUP;
2827 else
2828 lp->hupflags &= ~ISDN_CHARGEHUP;
2829 if (cfg->ihup)
2830 lp->hupflags |= ISDN_INHUP;
2831 else
2832 lp->hupflags &= ~ISDN_INHUP;
2833 if (cfg->chargeint > 10) {
2834 lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
2835 lp->chargeint = cfg->chargeint * HZ;
2836 }
2837 if (cfg->p_encap != lp->p_encap) {
2838 if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
Karsten Keild62a38d2007-10-08 20:37:11 -07002839 p->dev->header_ops = NULL;
Joe Perches475be4d2012-02-19 19:52:38 -08002840 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 } else {
Karsten Keild62a38d2007-10-08 20:37:11 -07002842 p->dev->header_ops = &isdn_header_ops;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002843 if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
Karsten Keild62a38d2007-10-08 20:37:11 -07002844 p->dev->flags = IFF_BROADCAST | IFF_MULTICAST;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07002845 else
Joe Perches475be4d2012-02-19 19:52:38 -08002846 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 }
2848 }
2849 lp->p_encap = cfg->p_encap;
2850 return 0;
2851 }
2852 return -ENODEV;
2853}
2854
2855/*
2856 * Perform get-interface-parameters.ioctl
2857 */
2858int
Joe Perches475be4d2012-02-19 19:52:38 -08002859isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860{
2861 isdn_net_dev *p = isdn_net_findif(cfg->name);
2862
2863 if (p) {
2864 isdn_net_local *lp = p->local;
2865
2866 strcpy(cfg->eaz, lp->msn);
2867 cfg->exclusive = lp->exclusive;
2868 if (lp->pre_device >= 0) {
2869 sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
2870 lp->pre_channel);
2871 } else
2872 cfg->drvid[0] = '\0';
2873 cfg->onhtime = lp->onhtime;
2874 cfg->charge = lp->charge;
2875 cfg->l2_proto = lp->l2_proto;
2876 cfg->l3_proto = lp->l3_proto;
2877 cfg->p_encap = lp->p_encap;
2878 cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
2879 cfg->callback = 0;
2880 if (lp->flags & ISDN_NET_CALLBACK)
2881 cfg->callback = 1;
2882 if (lp->flags & ISDN_NET_CBOUT)
2883 cfg->callback = 2;
2884 cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
2885 cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
Himangi Saraogi7b18ef02014-07-24 02:46:38 +05302886 cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
2887 cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888 cfg->cbdelay = lp->cbdelay;
2889 cfg->dialmax = lp->dialmax;
2890 cfg->triggercps = lp->triggercps;
2891 cfg->slavedelay = lp->slavedelay / HZ;
2892 cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
Joe Perches475be4d2012-02-19 19:52:38 -08002893 (lp->chargeint / HZ) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 cfg->pppbind = lp->pppbind;
2895 cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
2896 cfg->dialwait = lp->dialwait / HZ;
Karsten Keilfaca94f2007-10-15 02:11:44 -07002897 if (lp->slave) {
Dan Carpenter84ce9812010-07-10 04:31:11 +00002898 if (strlen(lp->slave->name) >= 10)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002899 strcpy(cfg->slave, "too-long");
2900 else
2901 strcpy(cfg->slave, lp->slave->name);
2902 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002903 cfg->slave[0] = '\0';
Karsten Keilfaca94f2007-10-15 02:11:44 -07002904 if (lp->master) {
Dan Carpenter84ce9812010-07-10 04:31:11 +00002905 if (strlen(lp->master->name) >= 10)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002906 strcpy(cfg->master, "too-long");
Dan Carpenter84ce9812010-07-10 04:31:11 +00002907 else
2908 strcpy(cfg->master, lp->master->name);
Karsten Keilfaca94f2007-10-15 02:11:44 -07002909 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 cfg->master[0] = '\0';
2911 return 0;
2912 }
2913 return -ENODEV;
2914}
2915
2916/*
2917 * Add a phone-number to an interface.
2918 */
2919int
Joe Perches475be4d2012-02-19 19:52:38 -08002920isdn_net_addphone(isdn_net_ioctl_phone *phone)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921{
2922 isdn_net_dev *p = isdn_net_findif(phone->name);
2923 isdn_net_phone *n;
2924
2925 if (p) {
Robert P. J. Day5cbded52006-12-13 00:35:56 -08002926 if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 return -ENOMEM;
Karsten Keil0f138642007-11-22 12:43:13 +01002928 strlcpy(n->num, phone->phone, sizeof(n->num));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 n->next = p->local->phone[phone->outgoing & 1];
2930 p->local->phone[phone->outgoing & 1] = n;
2931 return 0;
2932 }
2933 return -ENODEV;
2934}
2935
2936/*
2937 * Copy a string of all phone-numbers of an interface to user space.
2938 * This might sleep and must be called with the isdn semaphore down.
2939 */
2940int
Joe Perches475be4d2012-02-19 19:52:38 -08002941isdn_net_getphones(isdn_net_ioctl_phone *phone, char __user *phones)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002942{
2943 isdn_net_dev *p = isdn_net_findif(phone->name);
2944 int inout = phone->outgoing & 1;
2945 int more = 0;
2946 int count = 0;
2947 isdn_net_phone *n;
2948
2949 if (!p)
2950 return -ENODEV;
2951 inout &= 1;
2952 for (n = p->local->phone[inout]; n; n = n->next) {
2953 if (more) {
2954 put_user(' ', phones++);
2955 count++;
2956 }
2957 if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
2958 return -EFAULT;
2959 }
2960 phones += strlen(n->num);
2961 count += strlen(n->num);
2962 more = 1;
2963 }
2964 put_user(0, phones);
2965 count++;
2966 return count;
2967}
2968
2969/*
2970 * Copy a string containing the peer's phone number of a connected interface
2971 * to user space.
2972 */
2973int
2974isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
2975{
2976 isdn_net_dev *p = isdn_net_findif(phone->name);
2977 int ch, dv, idx;
2978
Karsten Keilfaca94f2007-10-15 02:11:44 -07002979 if (!p)
2980 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 /*
2982 * Theoretical race: while this executes, the remote number might
2983 * become invalid (hang up) or change (new connection), resulting
Joe Perches475be4d2012-02-19 19:52:38 -08002984 * in (partially) wrong number copied to user. This race
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 * currently ignored.
2986 */
2987 ch = p->local->isdn_channel;
2988 dv = p->local->isdn_device;
Joe Perches475be4d2012-02-19 19:52:38 -08002989 if (ch < 0 && dv < 0)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002990 return -ENOTCONN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 idx = isdn_dc2minor(dv, ch);
Joe Perches475be4d2012-02-19 19:52:38 -08002992 if (idx < 0)
Karsten Keilfaca94f2007-10-15 02:11:44 -07002993 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 /* for pre-bound channels, we need this extra check */
Karsten Keilfaca94f2007-10-15 02:11:44 -07002995 if (strncmp(dev->num[idx], "???", 3) == 0)
2996 return -ENOTCONN;
2997 strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
2998 phone->outgoing = USG_OUTGOING(dev->usage[idx]);
2999 if (copy_to_user(peer, phone, sizeof(*peer)))
3000 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 return 0;
3002}
3003/*
3004 * Delete a phone-number from an interface.
3005 */
3006int
Joe Perches475be4d2012-02-19 19:52:38 -08003007isdn_net_delphone(isdn_net_ioctl_phone *phone)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008{
3009 isdn_net_dev *p = isdn_net_findif(phone->name);
3010 int inout = phone->outgoing & 1;
3011 isdn_net_phone *n;
3012 isdn_net_phone *m;
3013
3014 if (p) {
3015 n = p->local->phone[inout];
3016 m = NULL;
3017 while (n) {
3018 if (!strcmp(n->num, phone->phone)) {
3019 if (p->local->dial == n)
3020 p->local->dial = n->next;
3021 if (m)
3022 m->next = n->next;
3023 else
3024 p->local->phone[inout] = n->next;
3025 kfree(n);
3026 return 0;
3027 }
3028 m = n;
3029 n = (isdn_net_phone *) n->next;
3030 }
3031 return -EINVAL;
3032 }
3033 return -ENODEV;
3034}
3035
3036/*
3037 * Delete all phone-numbers of an interface.
3038 */
3039static int
Joe Perches475be4d2012-02-19 19:52:38 -08003040isdn_net_rmallphone(isdn_net_dev *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041{
3042 isdn_net_phone *n;
3043 isdn_net_phone *m;
3044 int i;
3045
3046 for (i = 0; i < 2; i++) {
3047 n = p->local->phone[i];
3048 while (n) {
3049 m = n->next;
3050 kfree(n);
3051 n = m;
3052 }
3053 p->local->phone[i] = NULL;
3054 }
3055 p->local->dial = NULL;
3056 return 0;
3057}
3058
3059/*
3060 * Force a hangup of a network-interface.
3061 */
3062int
3063isdn_net_force_hangup(char *name)
3064{
3065 isdn_net_dev *p = isdn_net_findif(name);
3066 struct net_device *q;
3067
3068 if (p) {
3069 if (p->local->isdn_device < 0)
3070 return 1;
3071 q = p->local->slave;
3072 /* If this interface has slaves, do a hangup for them also. */
3073 while (q) {
3074 isdn_net_hangup(q);
Wang Chen838361f2008-12-03 15:49:46 -08003075 q = MASTER_TO_SLAVE(q);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
Karsten Keild62a38d2007-10-08 20:37:11 -07003077 isdn_net_hangup(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 return 0;
3079 }
3080 return -ENODEV;
3081}
3082
3083/*
3084 * Helper-function for isdn_net_rm: Do the real work.
3085 */
3086static int
Joe Perches475be4d2012-02-19 19:52:38 -08003087isdn_net_realrm(isdn_net_dev *p, isdn_net_dev *q)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088{
3089 u_long flags;
3090
3091 if (isdn_net_device_started(p)) {
3092 return -EBUSY;
3093 }
3094#ifdef CONFIG_ISDN_X25
Joe Perches475be4d2012-02-19 19:52:38 -08003095 if (p->cprot && p->cprot->pops)
3096 p->cprot->pops->proto_del(p->cprot);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097#endif
3098 /* Free all phone-entries */
3099 isdn_net_rmallphone(p);
3100 /* If interface is bound exclusive, free channel-usage */
3101 if (p->local->exclusive != -1)
3102 isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
3103 if (p->local->master) {
3104 /* It's a slave-device, so update master's slave-pointer if necessary */
Wang Chen838361f2008-12-03 15:49:46 -08003105 if (((isdn_net_local *) ISDN_MASTER_PRIV(p->local))->slave ==
3106 p->dev)
3107 ((isdn_net_local *)ISDN_MASTER_PRIV(p->local))->slave =
3108 p->local->slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 } else {
3110 /* Unregister only if it's a master-device */
Karsten Keild62a38d2007-10-08 20:37:11 -07003111 unregister_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 }
3113 /* Unlink device from chain */
3114 spin_lock_irqsave(&dev->lock, flags);
3115 if (q)
3116 q->next = p->next;
3117 else
3118 dev->netdev = p->next;
3119 if (p->local->slave) {
3120 /* If this interface has a slave, remove it also */
Karsten Keilfaca94f2007-10-15 02:11:44 -07003121 char *slavename = p->local->slave->name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122 isdn_net_dev *n = dev->netdev;
3123 q = NULL;
3124 while (n) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003125 if (!strcmp(n->dev->name, slavename)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 spin_unlock_irqrestore(&dev->lock, flags);
3127 isdn_net_realrm(n, q);
3128 spin_lock_irqsave(&dev->lock, flags);
3129 break;
3130 }
3131 q = n;
Karsten Keilfaca94f2007-10-15 02:11:44 -07003132 n = (isdn_net_dev *)n->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 }
3134 }
3135 spin_unlock_irqrestore(&dev->lock, flags);
3136 /* If no more net-devices remain, disable auto-hangup timer */
3137 if (dev->netdev == NULL)
3138 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
Karsten Keild62a38d2007-10-08 20:37:11 -07003139 free_netdev(p->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 kfree(p);
3141
3142 return 0;
3143}
3144
3145/*
3146 * Remove a single network-interface.
3147 */
3148int
3149isdn_net_rm(char *name)
3150{
3151 u_long flags;
3152 isdn_net_dev *p;
3153 isdn_net_dev *q;
3154
3155 /* Search name in netdev-chain */
3156 spin_lock_irqsave(&dev->lock, flags);
3157 p = dev->netdev;
3158 q = NULL;
3159 while (p) {
Karsten Keilfaca94f2007-10-15 02:11:44 -07003160 if (!strcmp(p->dev->name, name)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 spin_unlock_irqrestore(&dev->lock, flags);
3162 return (isdn_net_realrm(p, q));
3163 }
3164 q = p;
3165 p = (isdn_net_dev *) p->next;
3166 }
3167 spin_unlock_irqrestore(&dev->lock, flags);
3168 /* If no more net-devices remain, disable auto-hangup timer */
3169 if (dev->netdev == NULL)
3170 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3171 return -ENODEV;
3172}
3173
3174/*
3175 * Remove all network-interfaces
3176 */
3177int
3178isdn_net_rmall(void)
3179{
3180 u_long flags;
3181 int ret;
3182
3183 /* Walk through netdev-chain */
3184 spin_lock_irqsave(&dev->lock, flags);
3185 while (dev->netdev) {
3186 if (!dev->netdev->local->master) {
3187 /* Remove master-devices only, slaves get removed with their master */
3188 spin_unlock_irqrestore(&dev->lock, flags);
3189 if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
3190 return ret;
3191 }
3192 spin_lock_irqsave(&dev->lock, flags);
3193 }
3194 }
3195 dev->netdev = NULL;
3196 spin_unlock_irqrestore(&dev->lock, flags);
3197 return 0;
3198}