Commit 6e28ae46 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] generic HDLC updates

From: Krzysztof Halasa <khc@pm.waw.pl>

The following patch upgrades generic HDLC to support "new" protocol
handlers.
parent a51ae743
...@@ -116,7 +116,7 @@ static unsigned short cisco_type_trans(struct sk_buff *skb, ...@@ -116,7 +116,7 @@ static unsigned short cisco_type_trans(struct sk_buff *skb,
} }
static void cisco_rx(struct sk_buff *skb) static int cisco_rx(struct sk_buff *skb)
{ {
hdlc_device *hdlc = dev_to_hdlc(skb->dev); hdlc_device *hdlc = dev_to_hdlc(skb->dev);
hdlc_header *data = (hdlc_header*)skb->data; hdlc_header *data = (hdlc_header*)skb->data;
...@@ -131,24 +131,22 @@ static void cisco_rx(struct sk_buff *skb) ...@@ -131,24 +131,22 @@ static void cisco_rx(struct sk_buff *skb)
data->address != CISCO_UNICAST) data->address != CISCO_UNICAST)
goto rx_error; goto rx_error;
skb_pull(skb, sizeof(hdlc_header));
switch(ntohs(data->protocol)) { switch(ntohs(data->protocol)) {
case CISCO_SYS_INFO: case CISCO_SYS_INFO:
/* Packet is not needed, drop it. */ /* Packet is not needed, drop it. */
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_SUCCESS;
case CISCO_KEEPALIVE: case CISCO_KEEPALIVE:
if (skb->len != CISCO_PACKET_LEN && if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
skb->len != CISCO_BIG_PACKET_LEN) { skb->len != sizeof(hdlc_header) + CISCO_BIG_PACKET_LEN) {
printk(KERN_INFO "%s: Invalid length of Cisco " printk(KERN_INFO "%s: Invalid length of Cisco "
"control packet (%d bytes)\n", "control packet (%d bytes)\n",
hdlc_to_name(hdlc), skb->len); hdlc_to_name(hdlc), skb->len);
goto rx_error; goto rx_error;
} }
cisco_data = (cisco_packet*)skb->data; cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
switch(ntohl (cisco_data->type)) { switch(ntohl (cisco_data->type)) {
case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */ case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
...@@ -173,7 +171,7 @@ static void cisco_rx(struct sk_buff *skb) ...@@ -173,7 +171,7 @@ static void cisco_rx(struct sk_buff *skb)
addr, mask); addr, mask);
} }
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_SUCCESS;
case CISCO_ADDR_REPLY: case CISCO_ADDR_REPLY:
printk(KERN_INFO "%s: Unexpected Cisco IP address " printk(KERN_INFO "%s: Unexpected Cisco IP address "
...@@ -199,18 +197,19 @@ static void cisco_rx(struct sk_buff *skb) ...@@ -199,18 +197,19 @@ static void cisco_rx(struct sk_buff *skb)
} }
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_SUCCESS;
} /* switch(keepalive type) */ } /* switch(keepalive type) */
} /* switch(protocol) */ } /* switch(protocol) */
printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc), printk(KERN_INFO "%s: Unsupported protocol %x\n", hdlc_to_name(hdlc),
data->protocol); data->protocol);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_DROP;
rx_error: rx_error:
hdlc->stats.rx_errors++; /* Mark error */ hdlc->stats.rx_errors++; /* Mark error */
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NET_RX_DROP;
} }
......
...@@ -800,7 +800,7 @@ static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb) ...@@ -800,7 +800,7 @@ static int fr_lmi_recv(hdlc_device *hdlc, struct sk_buff *skb)
static void fr_rx(struct sk_buff *skb) static int fr_rx(struct sk_buff *skb)
{ {
hdlc_device *hdlc = dev_to_hdlc(skb->dev); hdlc_device *hdlc = dev_to_hdlc(skb->dev);
fr_hdr *fh = (fr_hdr*)skb->data; fr_hdr *fh = (fr_hdr*)skb->data;
...@@ -826,7 +826,7 @@ static void fr_rx(struct sk_buff *skb) ...@@ -826,7 +826,7 @@ static void fr_rx(struct sk_buff *skb)
hdlc->state.fr.request = 0; hdlc->state.fr.request = 0;
hdlc->state.fr.last_poll = jiffies; hdlc->state.fr.last_poll = jiffies;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_SUCCESS;
} }
} }
...@@ -842,7 +842,7 @@ static void fr_rx(struct sk_buff *skb) ...@@ -842,7 +842,7 @@ static void fr_rx(struct sk_buff *skb)
hdlc_to_name(hdlc), dlci); hdlc_to_name(hdlc), dlci);
#endif #endif
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_DROP;
} }
if (pvc->state.fecn != fh->fecn) { if (pvc->state.fecn != fh->fecn) {
...@@ -862,6 +862,11 @@ static void fr_rx(struct sk_buff *skb) ...@@ -862,6 +862,11 @@ static void fr_rx(struct sk_buff *skb)
} }
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
hdlc->stats.rx_dropped++;
return NET_RX_DROP;
}
if (data[3] == NLPID_IP) { if (data[3] == NLPID_IP) {
skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */
dev = pvc->main; dev = pvc->main;
...@@ -896,13 +901,13 @@ static void fr_rx(struct sk_buff *skb) ...@@ -896,13 +901,13 @@ static void fr_rx(struct sk_buff *skb)
printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
"PID=%x\n", hdlc_to_name(hdlc), oui, pid); "PID=%x\n", hdlc_to_name(hdlc), oui, pid);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_DROP;
} }
} else { } else {
printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
"length = %i\n", hdlc_to_name(hdlc), data[3], skb->len); "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return NET_RX_DROP;
} }
if (dev) { if (dev) {
...@@ -913,14 +918,16 @@ static void fr_rx(struct sk_buff *skb) ...@@ -913,14 +918,16 @@ static void fr_rx(struct sk_buff *skb)
stats->rx_compressed++; stats->rx_compressed++;
skb->dev = dev; skb->dev = dev;
netif_rx(skb); netif_rx(skb);
} else return NET_RX_SUCCESS;
} else {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NET_RX_DROP;
return; }
rx_error: rx_error:
hdlc->stats.rx_errors++; /* Mark error */ hdlc->stats.rx_errors++; /* Mark error */
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NET_RX_DROP;
} }
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <linux/hdlc.h> #include <linux/hdlc.h>
static const char* version = "HDLC support module revision 1.15"; static const char* version = "HDLC support module revision 1.16";
#undef DEBUG_LINK #undef DEBUG_LINK
...@@ -60,12 +60,11 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -60,12 +60,11 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
{ {
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.netif_rx) if (hdlc->proto.netif_rx)
hdlc->proto.netif_rx(skb); return hdlc->proto.netif_rx(skb);
else {
hdlc->stats.rx_dropped++; /* Shouldn't happen */ hdlc->stats.rx_dropped++; /* Shouldn't happen */
dev_kfree_skb(skb); dev_kfree_skb(skb);
} return NET_RX_DROP;
return 0;
} }
...@@ -280,10 +279,11 @@ EXPORT_SYMBOL(hdlc_ioctl); ...@@ -280,10 +279,11 @@ EXPORT_SYMBOL(hdlc_ioctl);
EXPORT_SYMBOL(register_hdlc_device); EXPORT_SYMBOL(register_hdlc_device);
EXPORT_SYMBOL(unregister_hdlc_device); EXPORT_SYMBOL(unregister_hdlc_device);
struct packet_type hdlc_packet_type= static struct packet_type hdlc_packet_type =
{ {
.type = __constant_htons(ETH_P_HDLC), .type = __constant_htons(ETH_P_HDLC),
.func = hdlc_rcv, .func = hdlc_rcv,
.data = (void *)1,
}; };
......
...@@ -164,14 +164,21 @@ static void x25_close(hdlc_device *hdlc) ...@@ -164,14 +164,21 @@ static void x25_close(hdlc_device *hdlc)
static void x25_rx(struct sk_buff *skb) static int x25_rx(struct sk_buff *skb)
{ {
hdlc_device *hdlc = dev_to_hdlc(skb->dev); hdlc_device *hdlc = dev_to_hdlc(skb->dev);
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
hdlc->stats.rx_dropped++;
return NET_RX_DROP;
}
if (lapb_data_received(hdlc, skb) == LAPB_OK) if (lapb_data_received(hdlc, skb) == LAPB_OK)
return; return NET_RX_SUCCESS;
hdlc->stats.rx_errors++; hdlc->stats.rx_errors++;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NET_RX_DROP;
} }
......
...@@ -118,7 +118,7 @@ typedef struct hdlc_device_struct { ...@@ -118,7 +118,7 @@ typedef struct hdlc_device_struct {
void (*stop)(struct hdlc_device_struct *hdlc); void (*stop)(struct hdlc_device_struct *hdlc);
void (*detach)(struct hdlc_device_struct *hdlc); void (*detach)(struct hdlc_device_struct *hdlc);
void (*netif_rx)(struct sk_buff *skb); int (*netif_rx)(struct sk_buff *skb);
unsigned short (*type_trans)(struct sk_buff *skb, unsigned short (*type_trans)(struct sk_buff *skb,
struct net_device *dev); struct net_device *dev);
int id; /* IF_PROTO_HDLC/CISCO/FR/etc. */ int id; /* IF_PROTO_HDLC/CISCO/FR/etc. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment