static void cisco_timer(unsigned long arg) { hdlc_device *hdlc=(hdlc_device*)arg; if ((hdlc->lmi.state & LINK_STATE_RELIABLE) && (jiffies - hdlc->lmi.last_poll >= hdlc->lmi.T392 * HZ)) { hdlc->lmi.state &= ~LINK_STATE_RELIABLE; printk(KERN_INFO "%s: Link down\n", hdlc->name); } cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ, ++hdlc->lmi.txseq, hdlc->lmi.rxseq); hdlc->timer.expires = jiffies + hdlc->lmi.T391*HZ; hdlc->timer.function = cisco_timer; hdlc->timer.data = arg; add_timer(&hdlc->timer); }
static void cisco_timer(unsigned long arg) { hdlc_device *hdlc = (hdlc_device*)arg; if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >= hdlc->state.cisco.settings.timeout * HZ) { hdlc->state.cisco.up = 0; printk(KERN_INFO "%s: Link down\n", hdlc_to_name(hdlc)); } cisco_keepalive_send(hdlc, CISCO_KEEPALIVE_REQ, ++hdlc->state.cisco.txseq, hdlc->state.cisco.rxseq); hdlc->state.cisco.timer.expires = jiffies + hdlc->state.cisco.settings.interval * HZ; hdlc->state.cisco.timer.function = cisco_timer; hdlc->state.cisco.timer.data = arg; add_timer(&hdlc->state.cisco.timer); }
static void cisco_timer(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; hdlc_device *hdlc = dev_to_hdlc(dev); if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >= hdlc->state.cisco.settings.timeout * HZ) { hdlc->state.cisco.up = 0; printk(KERN_INFO "%s: Link down\n", dev->name); if (netif_carrier_ok(dev)) netif_carrier_off(dev); } cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, ++hdlc->state.cisco.txseq, hdlc->state.cisco.rxseq); hdlc->state.cisco.timer.expires = jiffies + hdlc->state.cisco.settings.interval * HZ; hdlc->state.cisco.timer.function = cisco_timer; hdlc->state.cisco.timer.data = arg; add_timer(&hdlc->state.cisco.timer); }
static void cisco_timer(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; hdlc_device *hdlc = dev_to_hdlc(dev); struct cisco_state *st = state(hdlc); spin_lock(&st->lock); if (st->up && time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) { st->up = 0; netdev_info(dev, "Link down\n"); netif_dormant_on(dev); } cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq), htonl(st->rxseq)); spin_unlock(&st->lock); st->timer.expires = jiffies + st->settings.interval * HZ; st->timer.function = cisco_timer; st->timer.data = arg; add_timer(&st->timer); }
static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); struct cisco_state *st = state(hdlc); struct hdlc_header *data = (struct hdlc_header*)skb->data; struct cisco_packet *cisco_data; struct in_device *in_dev; __be32 addr, mask; u32 ack; if (skb->len < sizeof(struct hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) goto rx_error; switch (ntohs(data->protocol)) { case CISCO_SYS_INFO: /* Packet is not needed, drop it. */ dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_KEEPALIVE: if ((skb->len != sizeof(struct hdlc_header) + CISCO_PACKET_LEN) && (skb->len != sizeof(struct hdlc_header) + CISCO_BIG_PACKET_LEN)) { netdev_info(dev, "Invalid length of Cisco control packet (%d bytes)\n", skb->len); goto rx_error; } cisco_data = (struct cisco_packet*)(skb->data + sizeof (struct hdlc_header)); switch (ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); addr = 0; mask = ~cpu_to_be32(0); /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; while (*ifap != NULL) { if (strcmp(dev->name, (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; break; } ifap = &(*ifap)->ifa_next; } cisco_keepalive_send(dev, CISCO_ADDR_REPLY, addr, mask); } rcu_read_unlock(); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; case CISCO_ADDR_REPLY: netdev_info(dev, "Unexpected Cisco IP address reply\n"); goto rx_error; case CISCO_KEEPALIVE_REQ: spin_lock(&st->lock); st->rxseq = ntohl(cisco_data->par1); ack = ntohl(cisco_data->par2); if (ack && (ack == st->txseq || /* our current REQ may be in transit */ ack == st->txseq - 1)) { st->last_poll = jiffies; if (!st->up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; netdev_info(dev, "Link up (peer uptime %ud%uh%um%us)\n", days, hrs, min, sec); netif_dormant_off(dev); st->up = 1; } } spin_unlock(&st->lock); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; } /* switch (keepalive type) */ } /* switch (protocol) */ netdev_info(dev, "Unsupported protocol %x\n", ntohs(data->protocol)); dev_kfree_skb_any(skb); return NET_RX_DROP; rx_error: dev->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); return NET_RX_DROP; }
static void cisco_rx(struct sk_buff *skb) { hdlc_device *hdlc = dev_to_hdlc(skb->dev); hdlc_header *data = (hdlc_header*)skb->data; cisco_packet *cisco_data; struct in_device *in_dev; u32 addr, mask; if (skb->len < sizeof(hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) goto rx_error; skb_pull(skb, sizeof(hdlc_header)); switch(ntohs(data->protocol)) { case CISCO_SYS_INFO: /* Packet is not needed, drop it. */ dev_kfree_skb_any(skb); return; case CISCO_KEEPALIVE: if (skb->len != CISCO_PACKET_LEN && skb->len != CISCO_BIG_PACKET_LEN) { printk(KERN_INFO "%s: Invalid length of Cisco " "control packet (%d bytes)\n", hdlc_to_name(hdlc), skb->len); goto rx_error; } cisco_data = (cisco_packet*)skb->data; switch(ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ in_dev = hdlc_to_dev(hdlc)->ip_ptr; addr = 0; mask = ~0; /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap = &in_dev->ifa_list; while (*ifap != NULL) { if (strcmp(hdlc_to_name(hdlc), (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; break; } ifap = &(*ifap)->ifa_next; } cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY, addr, mask); } dev_kfree_skb_any(skb); return; case CISCO_ADDR_REPLY: printk(KERN_INFO "%s: Unexpected Cisco IP address " "reply\n", hdlc_to_name(hdlc)); goto rx_error; case CISCO_KEEPALIVE_REQ: hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); if (ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { hdlc->state.cisco.last_poll = jiffies; if (!hdlc->state.cisco.up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; printk(KERN_INFO "%s: Link up (peer " "uptime %ud%uh%um%us)\n", hdlc_to_name(hdlc), days, hrs, min, sec); } hdlc->state.cisco.up = 1; } dev_kfree_skb_any(skb); return; } /* switch(keepalive type) */ } /* switch(protocol) */ printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc), data->protocol); dev_kfree_skb_any(skb); return; rx_error: hdlc->stats.rx_errors++; /* Mark error */ dev_kfree_skb_any(skb); }
static void cisco_netif(hdlc_device *hdlc, struct sk_buff *skb) { hdlc_header *data = (hdlc_header*)skb->data; cisco_packet *cisco_data; if (skb->len<sizeof(hdlc_header)) goto rx_error; if (data->address != CISCO_MULTICAST && data->address != CISCO_UNICAST) goto rx_error; skb_pull(skb, sizeof(hdlc_header)); switch(ntohs(data->protocol)) { #ifdef CONFIG_INET case ETH_P_IP: #endif #ifdef CONFIG_IPX case ETH_P_IPX: #endif #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case ETH_P_IPV6: #endif #if defined(CONFIG_INET) || defined(CONFIG_IPX) || \ defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) hdlc->stats.rx_packets++; /* data traffic */ hdlc->stats.rx_bytes+=skb->len; skb->protocol=data->protocol; skb->dev=hdlc_to_dev(hdlc); netif_rx(skb); return; #endif case CISCO_KEEPALIVE: if (skb->len != CISCO_PACKET_LEN && skb->len != CISCO_BIG_PACKET_LEN) { printk(KERN_INFO "%s: Invalid length of Cisco " "control packet (%d bytes)\n", hdlc->name, skb->len); goto rx_error; } cisco_data=(cisco_packet*)skb->data; switch(ntohl (cisco_data->type)) { case CISCO_ADDR_REQ: { /* Stolen from syncppp.c :-) */ struct in_device *in_dev=hdlc_to_dev(hdlc)->ip_ptr; u32 addr = 0, mask = ~0; /* is the mask correct? */ if (in_dev != NULL) { struct in_ifaddr **ifap=&in_dev->ifa_list; while (*ifap != NULL) { if (strcmp(hdlc_to_dev(hdlc)->name, (*ifap)->ifa_label) == 0) { addr = (*ifap)->ifa_local; mask = (*ifap)->ifa_mask; break; } ifap=&(*ifap)->ifa_next; } hdlc->stats.rx_bytes+=skb->len; hdlc->stats.rx_packets++; cisco_keepalive_send(hdlc, CISCO_ADDR_REPLY, addr, mask); return; } } case CISCO_ADDR_REPLY: printk(KERN_INFO "%s: Unexpected Cisco IP address " "reply\n", hdlc->name); goto rx_error; case CISCO_KEEPALIVE_REQ: hdlc->lmi.rxseq = ntohl(cisco_data->par1); if (ntohl(cisco_data->par2) == hdlc->lmi.txseq) { hdlc->lmi.last_poll = jiffies; if (!(hdlc->lmi.state & LINK_STATE_RELIABLE)) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time)/1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; printk(KERN_INFO "%s: Link up (peer uptime %ud%uh%um%us)\n", hdlc->name, days, hrs, min, sec); } hdlc->lmi.state |= LINK_STATE_RELIABLE; } hdlc->stats.rx_bytes+=skb->len; hdlc->stats.rx_packets++; dev_kfree_skb(skb); return; } /* switch(keepalive type) */ } /* switch(protocol) */ printk(KERN_INFO "%s: Unusupported protocol %x\n", hdlc->name, data->protocol); hdlc->stats.rx_bytes+=skb->len; hdlc->stats.rx_packets++; dev_kfree_skb(skb); return; rx_error: hdlc->stats.rx_errors++; /* Mark error */ dev_kfree_skb(skb); }