include arp.h, required for 2.6.23
[~emulex/for-vlad/old/compat.git] / compat / compat-2.6.24.c
1 /*
2  * Copyright 2007       Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * Compatibility file for Linux wireless for kernels 2.6.24.
9  */
10
11 #include <net/compat.h>
12
13 /* All things not in 2.6.22 and 2.6.23 */
14 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24))
15
16 #include <net/arp.h>
17
18 /* Part of net/ethernet/eth.c as of 2.6.24 */
19 char *print_mac(char *buf, const u8 *addr)
20 {
21         sprintf(buf, MAC_FMT,
22                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
23         return buf;
24 }
25 EXPORT_SYMBOL(print_mac);
26
27 /* On net/core/dev.c as of 2.6.24 */
28 int __dev_addr_delete(struct dev_addr_list **list, int *count,
29                       void *addr, int alen, int glbl)
30 {
31         struct dev_addr_list *da;
32
33         for (; (da = *list) != NULL; list = &da->next) {
34                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
35                         alen == da->da_addrlen) {
36                         if (glbl) {
37                                 int old_glbl = da->da_gusers;
38                                 da->da_gusers = 0;
39                                 if (old_glbl == 0)
40                                         break;
41                         }
42                         if (--da->da_users)
43                                 return 0;
44
45                         *list = da->next;
46                         kfree(da);
47                         (*count)--;
48                         return 0;
49                 }
50         }
51         return -ENOENT;
52 }
53
54 /* On net/core/dev.c as of 2.6.24. This is not yet used by mac80211 but
55  * might as well add it */
56 int __dev_addr_add(struct dev_addr_list **list, int *count,
57                    void *addr, int alen, int glbl)
58 {
59         struct dev_addr_list *da;
60
61         for (da = *list; da != NULL; da = da->next) {
62                 if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
63                         da->da_addrlen == alen) {
64                         if (glbl) {
65                                 int old_glbl = da->da_gusers;
66                                 da->da_gusers = 1;
67                                 if (old_glbl)
68                                         return 0;
69                         }
70                         da->da_users++;
71                         return 0;
72                 }
73         }
74
75         da = kmalloc(sizeof(*da), GFP_ATOMIC);
76         if (da == NULL)
77                 return -ENOMEM;
78         memcpy(da->da_addr, addr, alen);
79         da->da_addrlen = alen;
80         da->da_users = 1;
81         da->da_gusers = glbl ? 1 : 0;
82         da->next = *list;
83         *list = da;
84         (*count)++;
85         return 0;
86 }
87
88 /* 2.6.22 and 2.6.23 have eth_header_cache_update defined as extern in include/linux/etherdevice.h
89  * and actually defined in net/ethernet/eth.c but 2.6.24 exports it. Lets export it here */
90
91 /**
92  * eth_header_cache_update - update cache entry
93  * @hh: destination cache entry
94  * @dev: network device
95  * @haddr: new hardware address
96  *
97  * Called by Address Resolution module to notify changes in address.
98  */
99 void eth_header_cache_update(struct hh_cache *hh,
100                              struct net_device *dev,
101                              unsigned char *haddr)
102 {
103         memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)),
104                 haddr, ETH_ALEN);
105 }
106 EXPORT_SYMBOL(eth_header_cache_update);
107
108 /* 2.6.22 and 2.6.23 have eth_header_cache defined as extern in include/linux/etherdevice.h
109  * and actually defined in net/ethernet/eth.c but 2.6.24 exports it. Lets export it here */
110
111 /**
112  * eth_header_cache - fill cache entry from neighbour
113  * @neigh: source neighbour
114  * @hh: destination cache entry
115  * Create an Ethernet header template from the neighbour.
116  */
117 int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
118 {
119         __be16 type = hh->hh_type;
120         struct ethhdr *eth;
121         const struct net_device *dev = neigh->dev;
122
123         eth = (struct ethhdr *)
124             (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth))));
125
126         if (type == htons(ETH_P_802_3))
127                 return -1;
128
129         eth->h_proto = type;
130         memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
131         memcpy(eth->h_dest, neigh->ha, ETH_ALEN);
132         hh->hh_len = ETH_HLEN;
133         return 0;
134 }
135 EXPORT_SYMBOL(eth_header_cache);
136
137 /* 2.6.22 and 2.6.23 have eth_header() defined as extern in include/linux/etherdevice.h
138  * and actually defined in net/ethernet/eth.c but 2.6.24 exports it. Lets export it here */
139
140 /**
141  * eth_header - create the Ethernet header
142  * @skb:        buffer to alter
143  * @dev:        source device
144  * @type:       Ethernet type field
145  * @daddr: destination address (NULL leave destination address)
146  * @saddr: source address (NULL use device source address)
147  * @len:   packet length (<= skb->len)
148  *
149  *
150  * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
151  * in here instead. It is up to the 802.2 layer to carry protocol information.
152  */
153 int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
154                void *daddr, void *saddr, unsigned len)
155 {
156         struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
157
158         if (type != ETH_P_802_3)
159                 eth->h_proto = htons(type);
160         else
161                 eth->h_proto = htons(len);
162
163         /*
164          *      Set the source hardware address.
165          */
166
167         if (!saddr)
168                 saddr = dev->dev_addr;
169         memcpy(eth->h_source, saddr, dev->addr_len);
170
171         if (daddr) {
172                 memcpy(eth->h_dest, daddr, dev->addr_len);
173                 return ETH_HLEN;
174         }
175
176         /*
177          *      Anyway, the loopback-device should never use this function...
178          */
179
180         if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
181                 memset(eth->h_dest, 0, dev->addr_len);
182                 return ETH_HLEN;
183         }
184
185         return -ETH_HLEN;
186 }
187
188 EXPORT_SYMBOL(eth_header);
189
190 /* 2.6.22 and 2.6.23 have eth_rebuild_header defined as extern in include/linux/etherdevice.h
191  * and actually defined in net/ethernet/eth.c but 2.6.24 exports it. Lets export it here */
192
193 /**
194  * eth_rebuild_header- rebuild the Ethernet MAC header.
195  * @skb: socket buffer to update
196  *
197  * This is called after an ARP or IPV6 ndisc it's resolution on this
198  * sk_buff. We now let protocol (ARP) fill in the other fields.
199  *
200  * This routine CANNOT use cached dst->neigh!
201  * Really, it is used only when dst->neigh is wrong.
202  */
203 int eth_rebuild_header(struct sk_buff *skb)
204 {
205         struct ethhdr *eth = (struct ethhdr *)skb->data;
206         struct net_device *dev = skb->dev;
207
208         switch (eth->h_proto) {
209 #ifdef CONFIG_INET
210         case __constant_htons(ETH_P_IP):
211                 return arp_find(eth->h_dest, skb);
212 #endif
213         default:
214                 printk(KERN_DEBUG
215                        "%s: unable to resolve type %X addresses.\n",
216                        dev->name, (int)eth->h_proto);
217
218                 memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
219                 break;
220         }
221
222         return 0;
223 }
224 EXPORT_SYMBOL(eth_rebuild_header);
225
226 /* 2.6.24 will introduce struct pci_dev is_pcie bit. To help
227  * with the compatibility code (compat.diff) being smaller, we provide a helper
228  * so in cases where that will be used we can simply slap ifdefs with this
229  * routine. Use compat_ prefex to not pollute namespace.  */
230 int compat_is_pcie(struct pci_dev *pdev)
231 {
232         int cap;
233         cap = pci_find_capability(pdev, PCI_CAP_ID_EXP);
234         return cap ? 1 : 0;
235 }
236 EXPORT_SYMBOL(compat_is_pcie);
237
238 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) */
239