]> git.hungrycats.org Git - linux/commitdiff
[PATCH] generic HDLC updates
authorAndrew Morton <akpm@osdl.org>
Fri, 1 Aug 2003 03:11:11 +0000 (20:11 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Fri, 1 Aug 2003 03:11:11 +0000 (20:11 -0700)
From: Krzysztof Halasa <khc@pm.waw.pl>

The following patch upgrades generic HDLC to support "new" protocol
handlers.

drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_generic.c
drivers/net/wan/hdlc_x25.c
include/linux/hdlc.h

index c639524042c5738025f92736eafa20198bdff668..b9723d8793e8fa529b18de59e6ce283a1f2c9c79 100644 (file)
@@ -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_header *data = (hdlc_header*)skb->data;
@@ -131,24 +131,22 @@ static void cisco_rx(struct sk_buff *skb)
            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;
+               return NET_RX_SUCCESS;
 
        case CISCO_KEEPALIVE:
-               if (skb->len != CISCO_PACKET_LEN &&
-                   skb->len != CISCO_BIG_PACKET_LEN) {
+               if (skb->len != sizeof(hdlc_header) + CISCO_PACKET_LEN &&
+                   skb->len != sizeof(hdlc_header) + 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;
+               cisco_data = (cisco_packet*)(skb->data + sizeof(hdlc_header));
 
                switch(ntohl (cisco_data->type)) {
                case CISCO_ADDR_REQ: /* Stolen from syncppp.c :-) */
@@ -173,7 +171,7 @@ static void cisco_rx(struct sk_buff *skb)
                                                     addr, mask);
                        }
                        dev_kfree_skb_any(skb);
-                       return;
+                       return NET_RX_SUCCESS;
 
                case CISCO_ADDR_REPLY:
                        printk(KERN_INFO "%s: Unexpected Cisco IP address "
@@ -199,18 +197,19 @@ static void cisco_rx(struct sk_buff *skb)
                        }
 
                        dev_kfree_skb_any(skb);
-                       return;
+                       return NET_RX_SUCCESS;
                } /* 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;
+       return NET_RX_DROP;
 
  rx_error:
        hdlc->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
+       return NET_RX_DROP;
 }
 
 
index 45cbde46c34f3bf6275c46d20e5f432468c90a92..dcf2b3b313b837170cdc9a8b3971da3fdaa518a8 100644 (file)
@@ -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);
        fr_hdr *fh = (fr_hdr*)skb->data;
@@ -826,7 +826,7 @@ static void fr_rx(struct sk_buff *skb)
                                hdlc->state.fr.request = 0;
                                hdlc->state.fr.last_poll = jiffies;
                                dev_kfree_skb_any(skb);
-                               return;
+                               return NET_RX_SUCCESS;
                        }
                }
 
@@ -842,7 +842,7 @@ static void fr_rx(struct sk_buff *skb)
                       hdlc_to_name(hdlc), dlci);
 #endif
                dev_kfree_skb_any(skb);
-               return;
+               return NET_RX_DROP;
        }
 
        if (pvc->state.fecn != fh->fecn) {
@@ -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) {
                skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */
                dev = pvc->main;
@@ -896,13 +901,13 @@ static void fr_rx(struct sk_buff *skb)
                        printk(KERN_INFO "%s: Unsupported protocol, OUI=%x "
                               "PID=%x\n", hdlc_to_name(hdlc), oui, pid);
                        dev_kfree_skb_any(skb);
-                       return;
+                       return NET_RX_DROP;
                }
        } else {
                printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x "
                       "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len);
                dev_kfree_skb_any(skb);
-               return;
+               return NET_RX_DROP;
        }
 
        if (dev) {
@@ -913,14 +918,16 @@ static void fr_rx(struct sk_buff *skb)
                        stats->rx_compressed++;
                skb->dev = dev;
                netif_rx(skb);
-       } else
+               return NET_RX_SUCCESS;
+       } else {
                dev_kfree_skb_any(skb);
-
-       return;
+               return NET_RX_DROP;
+       }
 
  rx_error:
        hdlc->stats.rx_errors++; /* Mark error */
        dev_kfree_skb_any(skb);
+       return NET_RX_DROP;
 }
 
 
index 4d150428ec8938a8ac2e9ee8341b2379b5a3aa4d..f9f37fcb0df50589396e95e4690858e072d02bc9 100644 (file)
@@ -33,7 +33,7 @@
 #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
 
@@ -60,12 +60,11 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
 {
        hdlc_device *hdlc = dev_to_hdlc(dev);
        if (hdlc->proto.netif_rx)
-               hdlc->proto.netif_rx(skb);
-       else {
-               hdlc->stats.rx_dropped++; /* Shouldn't happen */
-               dev_kfree_skb(skb);
-       }
-       return 0;
+               return hdlc->proto.netif_rx(skb);
+
+       hdlc->stats.rx_dropped++; /* Shouldn't happen */
+       dev_kfree_skb(skb);
+       return NET_RX_DROP;
 }
 
 
@@ -280,10 +279,11 @@ EXPORT_SYMBOL(hdlc_ioctl);
 EXPORT_SYMBOL(register_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),
        .func = hdlc_rcv,
+       .data = (void *)1,
 };
 
 
index 7433c966028e7cc19d9ff04faefec621df692bf0..3f0612c4c4be34c8ab0d067da412f2753e4779dd 100644 (file)
@@ -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);
 
+       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)
-               return;
+               return NET_RX_SUCCESS;
+
        hdlc->stats.rx_errors++;
        dev_kfree_skb_any(skb);
+       return NET_RX_DROP;
 }
 
 
index 94c967d945e7b23e3afc56f9826b1cf31fe95b23..7b35bd07943938675741fcd3e255647d2809e72e 100644 (file)
@@ -118,7 +118,7 @@ typedef struct hdlc_device_struct {
                void (*stop)(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,
                                             struct net_device *dev);
                int id;         /* IF_PROTO_HDLC/CISCO/FR/etc. */