1 /* 2 * Generic HDLC support routines for Linux 3 * X.25 support 4 * 5 * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of version 2 of the GNU General Public License 9 * as published by the Free Software Foundation. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/kernel.h> 14 #include <linux/slab.h> 15 #include <linux/poll.h> 16 #include <linux/errno.h> 17 #include <linux/if_arp.h> 18 #include <linux/init.h> 19 #include <linux/skbuff.h> 20 #include <linux/pkt_sched.h> 21 #include <linux/inetdevice.h> 22 #include <linux/lapb.h> 23 #include <linux/rtnetlink.h> 24 #include <linux/hdlc.h> 25 26 #include <net/x25device.h> 27 28 /* These functions are callbacks called by LAPB layer */ 29 30 static void x25_connect_disconnect(struct net_device *dev, int reason, int code) 31 { 32 struct sk_buff *skb; 33 unsigned char *ptr; 34 35 if ((skb = dev_alloc_skb(1)) == NULL) { 36 printk(KERN_ERR "%s: out of memory\n", dev->name); 37 return; 38 } 39 40 ptr = skb_put(skb, 1); 41 *ptr = code; 42 43 skb->protocol = x25_type_trans(skb, dev); 44 netif_rx(skb); 45 } 46 47 48 49 static void x25_connected(struct net_device *dev, int reason) 50 { 51 x25_connect_disconnect(dev, reason, 1); 52 } 53 54 55 56 static void x25_disconnected(struct net_device *dev, int reason) 57 { 58 x25_connect_disconnect(dev, reason, 2); 59 } 60 61 62 63 static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) 64 { 65 unsigned char *ptr; 66 67 skb_push(skb, 1); 68 69 if (skb_cow(skb, 1)) 70 return NET_RX_DROP; 71 72 ptr = skb->data; 73 *ptr = 0; 74 75 skb->protocol = x25_type_trans(skb, dev); 76 return netif_rx(skb); 77 } 78 79 80 81 static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb) 82 { 83 hdlc_device *hdlc = dev_to_hdlc(dev); 84 hdlc->xmit(skb, dev); /* Ignore return value :-( */ 85 } 86 87 88 89 static int x25_xmit(struct sk_buff *skb, struct net_device *dev) 90 { 91 int result; 92 93 94 /* X.25 to LAPB */ 95 switch (skb->data[0]) { 96 case 0: /* Data to be transmitted */ 97 skb_pull(skb, 1); 98 if ((result = lapb_data_request(dev, skb)) != LAPB_OK) 99 dev_kfree_skb(skb); 100 return 0; 101 102 case 1: 103 if ((result = lapb_connect_request(dev))!= LAPB_OK) { 104 if (result == LAPB_CONNECTED) 105 /* Send connect confirm. msg to level 3 */ 106 x25_connected(dev, 0); 107 else 108 printk(KERN_ERR "%s: LAPB connect request " 109 "failed, error code = %i\n", 110 dev->name, result); 111 } 112 break; 113 114 case 2: 115 if ((result = lapb_disconnect_request(dev)) != LAPB_OK) { 116 if (result == LAPB_NOTCONNECTED) 117 /* Send disconnect confirm. msg to level 3 */ 118 x25_disconnected(dev, 0); 119 else 120 printk(KERN_ERR "%s: LAPB disconnect request " 121 "failed, error code = %i\n", 122 dev->name, result); 123 } 124 break; 125 126 default: /* to be defined */ 127 break; 128 } 129 130 dev_kfree_skb(skb); 131 return 0; 132 } 133 134 135 136 static int x25_open(struct net_device *dev) 137 { 138 struct lapb_register_struct cb; 139 int result; 140 141 cb.connect_confirmation = x25_connected; 142 cb.connect_indication = x25_connected; 143 cb.disconnect_confirmation = x25_disconnected; 144 cb.disconnect_indication = x25_disconnected; 145 cb.data_indication = x25_data_indication; 146 cb.data_transmit = x25_data_transmit; 147 148 result = lapb_register(dev, &cb); 149 if (result != LAPB_OK) 150 return result; 151 return 0; 152 } 153 154 155 156 static void x25_close(struct net_device *dev) 157 { 158 lapb_unregister(dev); 159 } 160 161 162 163 static int x25_rx(struct sk_buff *skb) 164 { 165 hdlc_device *hdlc = dev_to_hdlc(skb->dev); 166 167 if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { 168 hdlc->stats.rx_dropped++; 169 return NET_RX_DROP; 170 } 171 172 if (lapb_data_received(skb->dev, skb) == LAPB_OK) 173 return NET_RX_SUCCESS; 174 175 hdlc->stats.rx_errors++; 176 dev_kfree_skb_any(skb); 177 return NET_RX_DROP; 178 } 179 180 181 182 int hdlc_x25_ioctl(struct net_device *dev, struct ifreq *ifr) 183 { 184 hdlc_device *hdlc = dev_to_hdlc(dev); 185 int result; 186 187 switch (ifr->ifr_settings.type) { 188 case IF_GET_PROTO: 189 ifr->ifr_settings.type = IF_PROTO_X25; 190 return 0; /* return protocol only, no settable parameters */ 191 192 case IF_PROTO_X25: 193 if(!capable(CAP_NET_ADMIN)) 194 return -EPERM; 195 196 if(dev->flags & IFF_UP) 197 return -EBUSY; 198 199 result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); 200 if (result) 201 return result; 202 203 hdlc_proto_detach(hdlc); 204 memset(&hdlc->proto, 0, sizeof(hdlc->proto)); 205 206 hdlc->proto.open = x25_open; 207 hdlc->proto.close = x25_close; 208 hdlc->proto.netif_rx = x25_rx; 209 hdlc->proto.type_trans = NULL; 210 hdlc->proto.id = IF_PROTO_X25; 211 dev->hard_start_xmit = x25_xmit; 212 dev->hard_header = NULL; 213 dev->type = ARPHRD_X25; 214 dev->addr_len = 0; 215 netif_dormant_off(dev); 216 return 0; 217 } 218 219 return -EINVAL; 220 } 221