~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/netrom/nr_dev.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      NET/ROM release 007
  3  *
  4  *      This code REQUIRES 2.1.15 or higher/ NET3.038
  5  *
  6  *      This module:
  7  *              This module is free software; you can redistribute it and/or
  8  *              modify it under the terms of the GNU General Public License
  9  *              as published by the Free Software Foundation; either version
 10  *              2 of the License, or (at your option) any later version.
 11  *
 12  *      History
 13  *      NET/ROM 001     Jonathan(G4KLX) Cloned from loopback.c
 14  *      NET/ROM 002     Steve Whitehouse(GW7RRM) fixed the set_mac_address
 15  *      NET/ROM 003     Jonathan(G4KLX) Put nr_rebuild_header into line with
 16  *                                      ax25_rebuild_header
 17  *      NET/ROM 004     Jonathan(G4KLX) Callsign registration with AX.25.
 18  *      NET/ROM 006     Hans(PE1AYX)    Fixed interface to IP layer.
 19  */
 20 
 21 #include <linux/config.h>
 22 #define __NO_VERSION__
 23 #include <linux/module.h>
 24 #include <linux/proc_fs.h>
 25 #include <linux/kernel.h>
 26 #include <linux/sched.h>
 27 #include <linux/interrupt.h>
 28 #include <linux/fs.h>
 29 #include <linux/types.h>
 30 #include <linux/sysctl.h>
 31 #include <linux/string.h>
 32 #include <linux/socket.h>
 33 #include <linux/errno.h>
 34 #include <linux/fcntl.h>
 35 #include <linux/in.h>
 36 #include <linux/if_ether.h>     /* For the statistics structure. */
 37 
 38 #include <asm/system.h>
 39 #include <asm/uaccess.h>
 40 #include <asm/io.h>
 41 
 42 #include <linux/inet.h>
 43 #include <linux/netdevice.h>
 44 #include <linux/etherdevice.h>
 45 #include <linux/if_arp.h>
 46 #include <linux/skbuff.h>
 47 
 48 #include <net/ip.h>
 49 #include <net/arp.h>
 50 
 51 #include <net/ax25.h>
 52 #include <net/netrom.h>
 53 
 54 #ifdef CONFIG_INET
 55 
 56 /*
 57  *      Only allow IP over NET/ROM frames through if the netrom device is up.
 58  */
 59 
 60 int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
 61 {
 62         struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 63 
 64         if (!netif_running(dev)) {
 65                 stats->rx_errors++;
 66                 return 0;
 67         }
 68 
 69         stats->rx_packets++;
 70         stats->rx_bytes += skb->len;
 71 
 72         skb->protocol = htons(ETH_P_IP);
 73 
 74         /* Spoof incoming device */
 75         skb->dev      = dev;
 76         skb->h.raw    = skb->data;
 77         skb->nh.raw   = skb->data;
 78         skb->pkt_type = PACKET_HOST;
 79 
 80         ip_rcv(skb, skb->dev, NULL);
 81 
 82         return 1;
 83 }
 84 
 85 
 86 static int nr_rebuild_header(struct sk_buff *skb)
 87 {
 88         struct net_device *dev = skb->dev;
 89         struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 90         struct sk_buff *skbn;
 91         unsigned char *bp = skb->data;
 92 
 93         if (arp_find(bp + 7, skb)) {
 94                 return 1;
 95         }
 96 
 97         bp[6] &= ~AX25_CBIT;
 98         bp[6] &= ~AX25_EBIT;
 99         bp[6] |= AX25_SSSID_SPARE;
100         bp    += AX25_ADDR_LEN;
101 
102         bp[6] &= ~AX25_CBIT;
103         bp[6] |= AX25_EBIT;
104         bp[6] |= AX25_SSSID_SPARE;
105 
106         if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
107                 kfree_skb(skb);
108                 return 1;
109         }
110 
111         if (skb->sk != NULL)
112                 skb_set_owner_w(skbn, skb->sk);
113 
114         kfree_skb(skb);
115 
116         if (!nr_route_frame(skbn, NULL)) {
117                 kfree_skb(skbn);
118                 stats->tx_errors++;
119         }
120 
121         stats->tx_packets++;
122         stats->tx_bytes += skbn->len;
123 
124         return 1;
125 }
126 
127 #else
128 
129 static int nr_rebuild_header(struct sk_buff *skb)
130 {
131         return 1;
132 }
133 
134 #endif
135 
136 static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
137         void *daddr, void *saddr, unsigned len)
138 {
139         unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
140 
141         memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);
142         buff[6] &= ~AX25_CBIT;
143         buff[6] &= ~AX25_EBIT;
144         buff[6] |= AX25_SSSID_SPARE;
145         buff    += AX25_ADDR_LEN;
146 
147         if (daddr != NULL)
148                 memcpy(buff, daddr, dev->addr_len);
149         buff[6] &= ~AX25_CBIT;
150         buff[6] |= AX25_EBIT;
151         buff[6] |= AX25_SSSID_SPARE;
152         buff    += AX25_ADDR_LEN;
153 
154         *buff++ = sysctl_netrom_network_ttl_initialiser;
155 
156         *buff++ = NR_PROTO_IP;
157         *buff++ = NR_PROTO_IP;
158         *buff++ = 0;
159         *buff++ = 0;
160         *buff++ = NR_PROTOEXT;
161 
162         if (daddr != NULL)
163                 return 37;
164 
165         return -37;
166 }
167 
168 static int nr_set_mac_address(struct net_device *dev, void *addr)
169 {
170         struct sockaddr *sa = addr;
171 
172         ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
173 
174         memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
175 
176         ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
177 
178         return 0;
179 }
180 
181 static int nr_open(struct net_device *dev)
182 {
183         MOD_INC_USE_COUNT;
184         netif_start_queue(dev);
185         ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
186         return 0;
187 }
188 
189 static int nr_close(struct net_device *dev)
190 {
191         netif_stop_queue(dev);
192         ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
193         MOD_DEC_USE_COUNT;
194         return 0;
195 }
196 
197 static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
198 {
199         struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
200         dev_kfree_skb(skb);
201         stats->tx_errors++;
202         return 0;
203 }
204 
205 static struct net_device_stats *nr_get_stats(struct net_device *dev)
206 {
207         return (struct net_device_stats *)dev->priv;
208 }
209 
210 int nr_init(struct net_device *dev)
211 {
212         dev->mtu                = NR_MAX_PACKET_SIZE;
213         dev->hard_start_xmit    = nr_xmit;
214         dev->open               = nr_open;
215         dev->stop               = nr_close;
216 
217         dev->hard_header        = nr_header;
218         dev->hard_header_len    = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + NR_NETWORK_LEN + NR_TRANSPORT_LEN;
219         dev->addr_len           = AX25_ADDR_LEN;
220         dev->type               = ARPHRD_NETROM;
221         dev->rebuild_header     = nr_rebuild_header;
222         dev->set_mac_address    = nr_set_mac_address;
223 
224         /* New-style flags. */
225         dev->flags              = 0;
226 
227         if ((dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL)) == NULL)
228                 return -ENOMEM;
229 
230         memset(dev->priv, 0, sizeof(struct net_device_stats));
231 
232         dev->get_stats = nr_get_stats;
233 
234         dev_init_buffers(dev);
235 
236         return 0;
237 };
238 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.