1/*- 2 * Copyright (c) 1999, 2000 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
| 1/*- 2 * Copyright (c) 1999, 2000 Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
|
26 * $FreeBSD: head/sys/net/if_ef.c 111790 2003-03-03 05:04:57Z mdodd $
| 26 * $FreeBSD: head/sys/net/if_ef.c 111888 2003-03-04 23:19:55Z jlemon $
|
27 */ 28 29#include "opt_inet.h" 30#include "opt_ipx.h" 31#include "opt_ef.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/sockio.h> 36#include <sys/malloc.h> 37#include <sys/mbuf.h> 38#include <sys/socket.h> 39#include <sys/syslog.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42 43#include <net/ethernet.h> 44#include <net/if_llc.h> 45#include <net/if.h> 46#include <net/if_arp.h> 47#include <net/if_dl.h> 48#include <net/if_types.h> 49#include <net/netisr.h> 50#include <net/route.h> 51#include <net/bpf.h> 52 53#ifdef INET 54#include <netinet/in.h> 55#include <netinet/in_var.h> 56#include <netinet/if_ether.h> 57#endif 58 59#ifdef IPX 60#include <netipx/ipx.h> 61#include <netipx/ipx_if.h> 62#endif 63 64/* internal frame types */ 65#define ETHER_FT_EII 0 /* Ethernet_II - default */ 66#define ETHER_FT_8023 1 /* 802.3 (Novell) */ 67#define ETHER_FT_8022 2 /* 802.2 */ 68#define ETHER_FT_SNAP 3 /* SNAP */ 69#define EF_NFT 4 /* total number of frame types */ 70 71#ifdef EF_DEBUG 72#define EFDEBUG(format, args...) printf("%s: "format, __func__ ,## args) 73#else 74#define EFDEBUG(format, args...) 75#endif 76 77#define EFERROR(format, args...) printf("%s: "format, __func__ ,## args) 78 79struct efnet { 80 struct arpcom ef_ac; 81 struct ifnet * ef_ifp; 82}; 83 84struct ef_link { 85 SLIST_ENTRY(ef_link) el_next; 86 struct ifnet *el_ifp; /* raw device for this clones */ 87 struct efnet *el_units[EF_NFT]; /* our clones */ 88}; 89 90static SLIST_HEAD(ef_link_head, ef_link) efdev = {NULL}; 91static int efcount; 92 93extern int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 94extern int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 95 struct sockaddr *dst, short *tp, int *hlen); 96 97/* 98static void ef_reset (struct ifnet *); 99*/ 100static int ef_attach(struct efnet *sc); 101static int ef_detach(struct efnet *sc); 102static void ef_init(void *); 103static int ef_ioctl(struct ifnet *, u_long, caddr_t); 104static void ef_start(struct ifnet *); 105static int ef_input(struct ifnet*, struct ether_header *, struct mbuf *); 106static int ef_output(struct ifnet *ifp, struct mbuf **mp, 107 struct sockaddr *dst, short *tp, int *hlen); 108 109static int ef_load(void); 110static int ef_unload(void); 111 112/* 113 * Install the interface, most of structure initialization done in ef_clone() 114 */ 115static int 116ef_attach(struct efnet *sc) 117{ 118 struct ifnet *ifp = (struct ifnet*)&sc->ef_ac.ac_if; 119 struct ifaddr *ifa2; 120 struct sockaddr_dl *sdl2; 121 122 ifp->if_output = ether_output; 123 ifp->if_start = ef_start; 124 ifp->if_watchdog = NULL; 125 ifp->if_init = ef_init; 126 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 127 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 128 /* 129 * Attach the interface 130 */ 131 ifa2 = ifaddr_byindex(sc->ef_ifp->if_index); 132 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr; 133 ether_ifattach(ifp, LLADDR(sdl2)); 134 135 ifp->if_resolvemulti = 0; 136 ifp->if_type = IFT_XETHER; 137 ifp->if_flags |= IFF_RUNNING; 138 139 bcopy(LLADDR(sdl2), sc->ef_ac.ac_enaddr, ETHER_ADDR_LEN); 140 141 EFDEBUG("%s%d: attached\n", ifp->if_name, ifp->if_unit); 142 return 1; 143} 144 145/* 146 * This is for _testing_only_, just removes interface from interfaces list 147 */ 148static int 149ef_detach(struct efnet *sc) 150{ 151 struct ifnet *ifp = (struct ifnet*)&sc->ef_ac.ac_if; 152 int s; 153 154 s = splimp(); 155 156 if (ifp->if_flags & IFF_UP) { 157 if_down(ifp); 158 if (ifp->if_flags & IFF_RUNNING) { 159 /* find internet addresses and delete routes */ 160 register struct ifaddr *ifa; 161 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 162 rtinit(ifa, (int)RTM_DELETE, 0); 163 } 164 } 165 } 166 IFNET_WLOCK(); 167 TAILQ_REMOVE(&ifnet, ifp, if_link); 168 IFNET_WUNLOCK(); 169 splx(s); 170 return 0; 171} 172 173static void 174ef_init(void *foo) { 175 return; 176} 177 178static int 179ef_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 180{ 181/* struct ef_link *sc = (struct ef_link*)ifp->if_softc;*/ 182 struct ifaddr *ifa = (struct ifaddr*)data; 183 int s, error; 184 185 EFDEBUG("IOCTL %ld for %s%d\n", cmd, ifp->if_name, ifp->if_unit); 186 error = 0; 187 s = splimp(); 188 switch (cmd) { 189 case SIOCSIFFLAGS: 190 error = 0; 191 break; 192 case SIOCSIFADDR: 193 if (ifp->if_unit == ETHER_FT_8023 && 194 ifa->ifa_addr->sa_family != AF_IPX) { 195 error = EAFNOSUPPORT; 196 break; 197 } 198 ifp->if_flags |= IFF_UP; 199 /* FALL THROUGH */ 200 default: 201 error = ether_ioctl(ifp, cmd, data); 202 break; 203 } 204 splx(s); 205 return error; 206} 207 208/* 209 * Currently packet prepared in the ether_output(), but this can be a better 210 * place. 211 */ 212static void 213ef_start(struct ifnet *ifp) 214{ 215 struct efnet *sc = (struct efnet*)ifp->if_softc; 216 struct ifnet *p; 217 struct mbuf *m; 218 219 ifp->if_flags |= IFF_OACTIVE; 220 p = sc->ef_ifp; 221 222 EFDEBUG("\n"); 223 for (;;) { 224 IF_DEQUEUE(&ifp->if_snd, m); 225 if (m == 0) 226 break; 227 BPF_MTAP(ifp, m); 228 if (! IF_HANDOFF(&p->if_snd, m, p)) { 229 ifp->if_oerrors++; 230 continue; 231 } 232 ifp->if_opackets++; 233 } 234 ifp->if_flags &= ~IFF_OACTIVE; 235 return; 236} 237 238/* 239 * Inline functions do not put additional overhead to procedure call or 240 * parameter passing but simplify the code 241 */ 242static int __inline
| 27 */ 28 29#include "opt_inet.h" 30#include "opt_ipx.h" 31#include "opt_ef.h" 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/sockio.h> 36#include <sys/malloc.h> 37#include <sys/mbuf.h> 38#include <sys/socket.h> 39#include <sys/syslog.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42 43#include <net/ethernet.h> 44#include <net/if_llc.h> 45#include <net/if.h> 46#include <net/if_arp.h> 47#include <net/if_dl.h> 48#include <net/if_types.h> 49#include <net/netisr.h> 50#include <net/route.h> 51#include <net/bpf.h> 52 53#ifdef INET 54#include <netinet/in.h> 55#include <netinet/in_var.h> 56#include <netinet/if_ether.h> 57#endif 58 59#ifdef IPX 60#include <netipx/ipx.h> 61#include <netipx/ipx_if.h> 62#endif 63 64/* internal frame types */ 65#define ETHER_FT_EII 0 /* Ethernet_II - default */ 66#define ETHER_FT_8023 1 /* 802.3 (Novell) */ 67#define ETHER_FT_8022 2 /* 802.2 */ 68#define ETHER_FT_SNAP 3 /* SNAP */ 69#define EF_NFT 4 /* total number of frame types */ 70 71#ifdef EF_DEBUG 72#define EFDEBUG(format, args...) printf("%s: "format, __func__ ,## args) 73#else 74#define EFDEBUG(format, args...) 75#endif 76 77#define EFERROR(format, args...) printf("%s: "format, __func__ ,## args) 78 79struct efnet { 80 struct arpcom ef_ac; 81 struct ifnet * ef_ifp; 82}; 83 84struct ef_link { 85 SLIST_ENTRY(ef_link) el_next; 86 struct ifnet *el_ifp; /* raw device for this clones */ 87 struct efnet *el_units[EF_NFT]; /* our clones */ 88}; 89 90static SLIST_HEAD(ef_link_head, ef_link) efdev = {NULL}; 91static int efcount; 92 93extern int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 94extern int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 95 struct sockaddr *dst, short *tp, int *hlen); 96 97/* 98static void ef_reset (struct ifnet *); 99*/ 100static int ef_attach(struct efnet *sc); 101static int ef_detach(struct efnet *sc); 102static void ef_init(void *); 103static int ef_ioctl(struct ifnet *, u_long, caddr_t); 104static void ef_start(struct ifnet *); 105static int ef_input(struct ifnet*, struct ether_header *, struct mbuf *); 106static int ef_output(struct ifnet *ifp, struct mbuf **mp, 107 struct sockaddr *dst, short *tp, int *hlen); 108 109static int ef_load(void); 110static int ef_unload(void); 111 112/* 113 * Install the interface, most of structure initialization done in ef_clone() 114 */ 115static int 116ef_attach(struct efnet *sc) 117{ 118 struct ifnet *ifp = (struct ifnet*)&sc->ef_ac.ac_if; 119 struct ifaddr *ifa2; 120 struct sockaddr_dl *sdl2; 121 122 ifp->if_output = ether_output; 123 ifp->if_start = ef_start; 124 ifp->if_watchdog = NULL; 125 ifp->if_init = ef_init; 126 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 127 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 128 /* 129 * Attach the interface 130 */ 131 ifa2 = ifaddr_byindex(sc->ef_ifp->if_index); 132 sdl2 = (struct sockaddr_dl *)ifa2->ifa_addr; 133 ether_ifattach(ifp, LLADDR(sdl2)); 134 135 ifp->if_resolvemulti = 0; 136 ifp->if_type = IFT_XETHER; 137 ifp->if_flags |= IFF_RUNNING; 138 139 bcopy(LLADDR(sdl2), sc->ef_ac.ac_enaddr, ETHER_ADDR_LEN); 140 141 EFDEBUG("%s%d: attached\n", ifp->if_name, ifp->if_unit); 142 return 1; 143} 144 145/* 146 * This is for _testing_only_, just removes interface from interfaces list 147 */ 148static int 149ef_detach(struct efnet *sc) 150{ 151 struct ifnet *ifp = (struct ifnet*)&sc->ef_ac.ac_if; 152 int s; 153 154 s = splimp(); 155 156 if (ifp->if_flags & IFF_UP) { 157 if_down(ifp); 158 if (ifp->if_flags & IFF_RUNNING) { 159 /* find internet addresses and delete routes */ 160 register struct ifaddr *ifa; 161 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 162 rtinit(ifa, (int)RTM_DELETE, 0); 163 } 164 } 165 } 166 IFNET_WLOCK(); 167 TAILQ_REMOVE(&ifnet, ifp, if_link); 168 IFNET_WUNLOCK(); 169 splx(s); 170 return 0; 171} 172 173static void 174ef_init(void *foo) { 175 return; 176} 177 178static int 179ef_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 180{ 181/* struct ef_link *sc = (struct ef_link*)ifp->if_softc;*/ 182 struct ifaddr *ifa = (struct ifaddr*)data; 183 int s, error; 184 185 EFDEBUG("IOCTL %ld for %s%d\n", cmd, ifp->if_name, ifp->if_unit); 186 error = 0; 187 s = splimp(); 188 switch (cmd) { 189 case SIOCSIFFLAGS: 190 error = 0; 191 break; 192 case SIOCSIFADDR: 193 if (ifp->if_unit == ETHER_FT_8023 && 194 ifa->ifa_addr->sa_family != AF_IPX) { 195 error = EAFNOSUPPORT; 196 break; 197 } 198 ifp->if_flags |= IFF_UP; 199 /* FALL THROUGH */ 200 default: 201 error = ether_ioctl(ifp, cmd, data); 202 break; 203 } 204 splx(s); 205 return error; 206} 207 208/* 209 * Currently packet prepared in the ether_output(), but this can be a better 210 * place. 211 */ 212static void 213ef_start(struct ifnet *ifp) 214{ 215 struct efnet *sc = (struct efnet*)ifp->if_softc; 216 struct ifnet *p; 217 struct mbuf *m; 218 219 ifp->if_flags |= IFF_OACTIVE; 220 p = sc->ef_ifp; 221 222 EFDEBUG("\n"); 223 for (;;) { 224 IF_DEQUEUE(&ifp->if_snd, m); 225 if (m == 0) 226 break; 227 BPF_MTAP(ifp, m); 228 if (! IF_HANDOFF(&p->if_snd, m, p)) { 229 ifp->if_oerrors++; 230 continue; 231 } 232 ifp->if_opackets++; 233 } 234 ifp->if_flags &= ~IFF_OACTIVE; 235 return; 236} 237 238/* 239 * Inline functions do not put additional overhead to procedure call or 240 * parameter passing but simplify the code 241 */ 242static int __inline
|
243ef_inputEII(struct mbuf *m, struct ether_header *eh, 244 u_short ether_type, struct ifqueue **inq)
| 243ef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type)
|
245{
| 244{
|
| 245 int isr; 246
|
246 switch(ether_type) { 247#ifdef IPX
| 247 switch(ether_type) { 248#ifdef IPX
|
248 case ETHERTYPE_IPX: 249 schednetisr(NETISR_IPX); 250 *inq = &ipxintrq;
| 249 case ETHERTYPE_IPX: 250 isr = NETISR_IPX;
|
251 break; 252#endif 253#ifdef INET
| 251 break; 252#endif 253#ifdef INET
|
254 case ETHERTYPE_IP:
| 254 case ETHERTYPE_IP:
|
255 if (ipflow_fastforward(m))
| 255 if (ipflow_fastforward(m))
|
256 return 1; 257 schednetisr(NETISR_IP); 258 *inq = &ipintrq;
| 256 return (0); 257 isr = NETISR_IP;
|
259 break; 260
| 258 break; 259
|
261 case ETHERTYPE_ARP: 262 schednetisr(NETISR_ARP); 263 *inq = &arpintrq;
| 260 case ETHERTYPE_ARP: 261 isr = NETISR_ARP;
|
264 break; 265#endif
| 262 break; 263#endif
|
266 default: 267 return EPROTONOSUPPORT;
| 264 default: 265 return (EPROTONOSUPPORT);
|
268 }
| 266 }
|
269 return 0;
| 267 netisr_dispatch(isr, m); 268 return (0);
|
270} 271 272static int __inline 273ef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l,
| 269} 270 271static int __inline 272ef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l,
|
274 u_short ether_type, struct ifqueue **inq)
| 273 u_short ether_type)
|
275{
| 274{
|
| 275 int isr; 276
|
276 switch(ether_type) { 277#ifdef IPX
| 277 switch(ether_type) { 278#ifdef IPX
|
278 case ETHERTYPE_IPX:
| 279 case ETHERTYPE_IPX:
|
279 m_adj(m, 8);
| 280 m_adj(m, 8);
|
280 schednetisr(NETISR_IPX); 281 *inq = &ipxintrq;
| 281 isr = NETISR_IPX;
|
282 break; 283#endif
| 282 break; 283#endif
|
284 default: 285 return EPROTONOSUPPORT;
| 284 default: 285 return (EPROTONOSUPPORT);
|
286 }
| 286 }
|
287 return 0;
| 287 netisr_dispatch(isr, m); 288 return (0);
|
288} 289 290static int __inline 291ef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l,
| 289} 290 291static int __inline 292ef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l,
|
292 u_short ether_type, struct ifqueue **inq)
| 293 u_short ether_type)
|
293{
| 294{
|
| 295 int isr; 296
|
294 switch(ether_type) { 295#ifdef IPX
| 297 switch(ether_type) { 298#ifdef IPX
|
296 case 0xe0:
| 299 case 0xe0:
|
297 m_adj(m, 3);
| 300 m_adj(m, 3);
|
298 schednetisr(NETISR_IPX); 299 *inq = &ipxintrq;
| 301 isr = NETISR_IPX;
|
300 break; 301#endif
| 302 break; 303#endif
|
302 default: 303 return EPROTONOSUPPORT;
| 304 default: 305 return (EPROTONOSUPPORT);
|
304 }
| 306 }
|
305 return 0;
| 307 netisr_dispatch(isr, m); 308 return (0);
|
306}
| 309}
|
| 310
|
307/* 308 * Called from ether_input() 309 */ 310static int 311ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) 312{ 313 u_short ether_type; 314 int ft = -1;
| 311/* 312 * Called from ether_input() 313 */ 314static int 315ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) 316{ 317 u_short ether_type; 318 int ft = -1;
|
315 struct ifqueue *inq;
| |
316 struct efnet *efp; 317 struct ifnet *eifp; 318 struct llc *l; 319 struct ef_link *efl;
| 319 struct efnet *efp; 320 struct ifnet *eifp; 321 struct llc *l; 322 struct ef_link *efl;
|
| 323 int isr;
|
320 321 ether_type = ntohs(eh->ether_type); 322 if (ether_type < ETHERMTU) { 323 l = mtod(m, struct llc*); 324 if (l->llc_dsap == 0xff && l->llc_ssap == 0xff) { 325 /* 326 * Novell's "802.3" frame 327 */ 328 ft = ETHER_FT_8023; 329 } else if (l->llc_dsap == 0xaa && l->llc_ssap == 0xaa) { 330 /* 331 * 802.2/SNAP 332 */ 333 ft = ETHER_FT_SNAP; 334 ether_type = ntohs(l->llc_un.type_snap.ether_type); 335 } else if (l->llc_dsap == l->llc_ssap) { 336 /* 337 * 802.3/802.2 338 */ 339 ft = ETHER_FT_8022; 340 ether_type = l->llc_ssap; 341 } 342 } else 343 ft = ETHER_FT_EII; 344 345 if (ft == -1) { 346 EFDEBUG("Unrecognised ether_type %x\n", ether_type); 347 return EPROTONOSUPPORT; 348 } 349 350 /* 351 * Check if interface configured for the given frame 352 */ 353 efp = NULL; 354 SLIST_FOREACH(efl, &efdev, el_next) { 355 if (efl->el_ifp == ifp) { 356 efp = efl->el_units[ft]; 357 break; 358 } 359 } 360 if (efp == NULL) { 361 EFDEBUG("Can't find if for %d\n", ft); 362 return EPROTONOSUPPORT; 363 } 364 eifp = &efp->ef_ac.ac_if; 365 if ((eifp->if_flags & IFF_UP) == 0) 366 return EPROTONOSUPPORT; 367 eifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 368 m->m_pkthdr.rcvif = eifp; 369 370 if (eifp->if_bpf) { 371 struct mbuf m0; 372 m0.m_next = m; 373 m0.m_len = ETHER_HDR_LEN; 374 m0.m_data = (char *)eh; 375 BPF_MTAP(eifp, &m0); 376 } 377 /* 378 * Now we ready to adjust mbufs and pass them to protocol intr's 379 */
| 324 325 ether_type = ntohs(eh->ether_type); 326 if (ether_type < ETHERMTU) { 327 l = mtod(m, struct llc*); 328 if (l->llc_dsap == 0xff && l->llc_ssap == 0xff) { 329 /* 330 * Novell's "802.3" frame 331 */ 332 ft = ETHER_FT_8023; 333 } else if (l->llc_dsap == 0xaa && l->llc_ssap == 0xaa) { 334 /* 335 * 802.2/SNAP 336 */ 337 ft = ETHER_FT_SNAP; 338 ether_type = ntohs(l->llc_un.type_snap.ether_type); 339 } else if (l->llc_dsap == l->llc_ssap) { 340 /* 341 * 802.3/802.2 342 */ 343 ft = ETHER_FT_8022; 344 ether_type = l->llc_ssap; 345 } 346 } else 347 ft = ETHER_FT_EII; 348 349 if (ft == -1) { 350 EFDEBUG("Unrecognised ether_type %x\n", ether_type); 351 return EPROTONOSUPPORT; 352 } 353 354 /* 355 * Check if interface configured for the given frame 356 */ 357 efp = NULL; 358 SLIST_FOREACH(efl, &efdev, el_next) { 359 if (efl->el_ifp == ifp) { 360 efp = efl->el_units[ft]; 361 break; 362 } 363 } 364 if (efp == NULL) { 365 EFDEBUG("Can't find if for %d\n", ft); 366 return EPROTONOSUPPORT; 367 } 368 eifp = &efp->ef_ac.ac_if; 369 if ((eifp->if_flags & IFF_UP) == 0) 370 return EPROTONOSUPPORT; 371 eifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); 372 m->m_pkthdr.rcvif = eifp; 373 374 if (eifp->if_bpf) { 375 struct mbuf m0; 376 m0.m_next = m; 377 m0.m_len = ETHER_HDR_LEN; 378 m0.m_data = (char *)eh; 379 BPF_MTAP(eifp, &m0); 380 } 381 /* 382 * Now we ready to adjust mbufs and pass them to protocol intr's 383 */
|
380 inq = NULL;
| |
381 switch(ft) {
| 384 switch(ft) {
|
382 case ETHER_FT_EII: 383 if (ef_inputEII(m, eh, ether_type, &inq) != 0) 384 return EPROTONOSUPPORT;
| 385 case ETHER_FT_EII: 386 return (ef_inputEII(m, eh, ether_type));
|
385 break; 386#ifdef IPX
| 387 break; 388#ifdef IPX
|
387 case ETHER_FT_8023: /* only IPX can be here */ 388 schednetisr(NETISR_IPX); 389 inq = &ipxintrq;
| 389 case ETHER_FT_8023: /* only IPX can be here */ 390 isr = NETISR_IPX;
|
390 break; 391#endif
| 391 break; 392#endif
|
392 case ETHER_FT_SNAP: 393 if (ef_inputSNAP(m, eh, l, ether_type, &inq) != 0) 394 return EPROTONOSUPPORT;
| 393 case ETHER_FT_SNAP: 394 return (ef_inputSNAP(m, eh, l, ether_type));
|
395 break;
| 395 break;
|
396 case ETHER_FT_8022: 397 if (ef_input8022(m, eh, l, ether_type, &inq) != 0) 398 return EPROTONOSUPPORT;
| 396 case ETHER_FT_8022: 397 return (ef_input8022(m, eh, l, ether_type));
|
399 break;
| 398 break;
|
400 } 401 402 if (inq == NULL) {
| 399 default:
|
403 EFDEBUG("No support for frame %d and proto %04x\n", 404 ft, ether_type);
| 400 EFDEBUG("No support for frame %d and proto %04x\n", 401 ft, ether_type);
|
405 return EPROTONOSUPPORT;
| 402 return (EPROTONOSUPPORT);
|
406 }
| 403 }
|
407 (void) IF_HANDOFF(inq, m, NULL); 408 return 0;
| 404 netisr_dispatch(isr, m); 405 return (0);
|
409} 410 411static int 412ef_output(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, short *tp, 413 int *hlen) 414{ 415 struct mbuf *m = *mp; 416 u_char *cp; 417 short type; 418 419 if (ifp->if_type != IFT_XETHER) 420 return ENETDOWN; 421 switch (ifp->if_unit) { 422 case ETHER_FT_EII: 423#ifdef IPX 424 type = htons(ETHERTYPE_IPX); 425#else 426 return EPFNOSUPPORT; 427#endif 428 break; 429 case ETHER_FT_8023: 430 type = htons(m->m_pkthdr.len); 431 break; 432 case ETHER_FT_8022: 433 M_PREPEND(m, ETHER_HDR_LEN + 3, M_TRYWAIT); 434 if (m == NULL) { 435 *mp = NULL; 436 return ENOBUFS; 437 } 438 /* 439 * Ensure that ethernet header and next three bytes 440 * will fit into single mbuf 441 */ 442 m = m_pullup(m, ETHER_HDR_LEN + 3); 443 if (m == NULL) { 444 *mp = NULL; 445 return ENOBUFS; 446 } 447 m_adj(m, ETHER_HDR_LEN); 448 type = htons(m->m_pkthdr.len); 449 cp = mtod(m, u_char *); 450 *cp++ = 0xE0; 451 *cp++ = 0xE0; 452 *cp++ = 0x03; 453 *hlen += 3; 454 break; 455 case ETHER_FT_SNAP: 456 M_PREPEND(m, 8, M_TRYWAIT); 457 if (m == NULL) { 458 *mp = NULL; 459 return ENOBUFS; 460 } 461 type = htons(m->m_pkthdr.len); 462 cp = mtod(m, u_char *); 463 bcopy("\xAA\xAA\x03\x00\x00\x00\x81\x37", cp, 8); 464 *hlen += 8; 465 break; 466 default: 467 return EPFNOSUPPORT; 468 } 469 *mp = m; 470 *tp = type; 471 return 0; 472} 473 474/* 475 * Create clone from the given interface 476 */ 477static int 478ef_clone(struct ef_link *efl, int ft) 479{ 480 struct efnet *efp; 481 struct ifnet *eifp; 482 struct ifnet *ifp = efl->el_ifp; 483 char cbuf[IFNAMSIZ], *ifname; 484 int ifnlen; 485 486 efp = (struct efnet*)malloc(sizeof(struct efnet), M_IFADDR, 487 M_WAITOK | M_ZERO); 488 if (efp == NULL) 489 return ENOMEM; 490 efp->ef_ifp = ifp; 491 eifp = &efp->ef_ac.ac_if; 492 ifnlen = 1 + snprintf(cbuf, sizeof(cbuf), "%s%df", ifp->if_name, 493 ifp->if_unit); 494 ifname = (char*)malloc(ifnlen, M_IFADDR, M_WAITOK); 495 eifp->if_name = strcpy(ifname, cbuf); 496 eifp->if_unit = ft; 497 eifp->if_softc = efp; 498 if (ifp->if_ioctl) 499 eifp->if_ioctl = ef_ioctl; 500 efl->el_units[ft] = efp; 501 return 0; 502} 503 504static int 505ef_load(void) 506{ 507 struct ifnet *ifp; 508 struct efnet *efp; 509 struct ef_link *efl = NULL; 510 int error = 0, d; 511 512 IFNET_RLOCK(); 513 TAILQ_FOREACH(ifp, &ifnet, if_link) { 514 if (ifp->if_type != IFT_ETHER) continue; 515 EFDEBUG("Found interface %s%d\n", ifp->if_name, ifp->if_unit); 516 efl = (struct ef_link*)malloc(sizeof(struct ef_link), 517 M_IFADDR, M_WAITOK | M_ZERO); 518 if (efl == NULL) { 519 error = ENOMEM; 520 break; 521 } 522 523 efl->el_ifp = ifp; 524#ifdef ETHER_II 525 error = ef_clone(efl, ETHER_FT_EII); 526 if (error) break; 527#endif 528#ifdef ETHER_8023 529 error = ef_clone(efl, ETHER_FT_8023); 530 if (error) break; 531#endif 532#ifdef ETHER_8022 533 error = ef_clone(efl, ETHER_FT_8022); 534 if (error) break; 535#endif 536#ifdef ETHER_SNAP 537 error = ef_clone(efl, ETHER_FT_SNAP); 538 if (error) break; 539#endif 540 efcount++; 541 SLIST_INSERT_HEAD(&efdev, efl, el_next); 542 } 543 IFNET_RUNLOCK(); 544 if (error) { 545 if (efl) 546 SLIST_INSERT_HEAD(&efdev, efl, el_next); 547 SLIST_FOREACH(efl, &efdev, el_next) { 548 for (d = 0; d < EF_NFT; d++) 549 if (efl->el_units[d]) 550 free(efl->el_units[d], M_IFADDR); 551 free(efl, M_IFADDR); 552 } 553 return error; 554 } 555 SLIST_FOREACH(efl, &efdev, el_next) { 556 for (d = 0; d < EF_NFT; d++) { 557 efp = efl->el_units[d]; 558 if (efp) 559 ef_attach(efp); 560 } 561 } 562 ef_inputp = ef_input; 563 ef_outputp = ef_output; 564 EFDEBUG("Loaded\n"); 565 return 0; 566} 567 568static int 569ef_unload(void) 570{ 571 struct efnet *efp; 572 struct ef_link *efl; 573 int d; 574 575 ef_inputp = NULL; 576 ef_outputp = NULL; 577 SLIST_FOREACH(efl, &efdev, el_next) { 578 for (d = 0; d < EF_NFT; d++) { 579 efp = efl->el_units[d]; 580 if (efp) { 581 ef_detach(efp); 582 } 583 } 584 } 585 EFDEBUG("Unloaded\n"); 586 return 0; 587} 588 589static int 590if_ef_modevent(module_t mod, int type, void *data) 591{ 592 switch ((modeventtype_t)type) { 593 case MOD_LOAD: 594 return ef_load(); 595 case MOD_UNLOAD: 596 return ef_unload(); 597 default: 598 break; 599 } 600 return 0; 601} 602 603static moduledata_t if_ef_mod = { 604 "if_ef", if_ef_modevent, NULL 605}; 606 607DECLARE_MODULE(if_ef, if_ef_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
| 406} 407 408static int 409ef_output(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, short *tp, 410 int *hlen) 411{ 412 struct mbuf *m = *mp; 413 u_char *cp; 414 short type; 415 416 if (ifp->if_type != IFT_XETHER) 417 return ENETDOWN; 418 switch (ifp->if_unit) { 419 case ETHER_FT_EII: 420#ifdef IPX 421 type = htons(ETHERTYPE_IPX); 422#else 423 return EPFNOSUPPORT; 424#endif 425 break; 426 case ETHER_FT_8023: 427 type = htons(m->m_pkthdr.len); 428 break; 429 case ETHER_FT_8022: 430 M_PREPEND(m, ETHER_HDR_LEN + 3, M_TRYWAIT); 431 if (m == NULL) { 432 *mp = NULL; 433 return ENOBUFS; 434 } 435 /* 436 * Ensure that ethernet header and next three bytes 437 * will fit into single mbuf 438 */ 439 m = m_pullup(m, ETHER_HDR_LEN + 3); 440 if (m == NULL) { 441 *mp = NULL; 442 return ENOBUFS; 443 } 444 m_adj(m, ETHER_HDR_LEN); 445 type = htons(m->m_pkthdr.len); 446 cp = mtod(m, u_char *); 447 *cp++ = 0xE0; 448 *cp++ = 0xE0; 449 *cp++ = 0x03; 450 *hlen += 3; 451 break; 452 case ETHER_FT_SNAP: 453 M_PREPEND(m, 8, M_TRYWAIT); 454 if (m == NULL) { 455 *mp = NULL; 456 return ENOBUFS; 457 } 458 type = htons(m->m_pkthdr.len); 459 cp = mtod(m, u_char *); 460 bcopy("\xAA\xAA\x03\x00\x00\x00\x81\x37", cp, 8); 461 *hlen += 8; 462 break; 463 default: 464 return EPFNOSUPPORT; 465 } 466 *mp = m; 467 *tp = type; 468 return 0; 469} 470 471/* 472 * Create clone from the given interface 473 */ 474static int 475ef_clone(struct ef_link *efl, int ft) 476{ 477 struct efnet *efp; 478 struct ifnet *eifp; 479 struct ifnet *ifp = efl->el_ifp; 480 char cbuf[IFNAMSIZ], *ifname; 481 int ifnlen; 482 483 efp = (struct efnet*)malloc(sizeof(struct efnet), M_IFADDR, 484 M_WAITOK | M_ZERO); 485 if (efp == NULL) 486 return ENOMEM; 487 efp->ef_ifp = ifp; 488 eifp = &efp->ef_ac.ac_if; 489 ifnlen = 1 + snprintf(cbuf, sizeof(cbuf), "%s%df", ifp->if_name, 490 ifp->if_unit); 491 ifname = (char*)malloc(ifnlen, M_IFADDR, M_WAITOK); 492 eifp->if_name = strcpy(ifname, cbuf); 493 eifp->if_unit = ft; 494 eifp->if_softc = efp; 495 if (ifp->if_ioctl) 496 eifp->if_ioctl = ef_ioctl; 497 efl->el_units[ft] = efp; 498 return 0; 499} 500 501static int 502ef_load(void) 503{ 504 struct ifnet *ifp; 505 struct efnet *efp; 506 struct ef_link *efl = NULL; 507 int error = 0, d; 508 509 IFNET_RLOCK(); 510 TAILQ_FOREACH(ifp, &ifnet, if_link) { 511 if (ifp->if_type != IFT_ETHER) continue; 512 EFDEBUG("Found interface %s%d\n", ifp->if_name, ifp->if_unit); 513 efl = (struct ef_link*)malloc(sizeof(struct ef_link), 514 M_IFADDR, M_WAITOK | M_ZERO); 515 if (efl == NULL) { 516 error = ENOMEM; 517 break; 518 } 519 520 efl->el_ifp = ifp; 521#ifdef ETHER_II 522 error = ef_clone(efl, ETHER_FT_EII); 523 if (error) break; 524#endif 525#ifdef ETHER_8023 526 error = ef_clone(efl, ETHER_FT_8023); 527 if (error) break; 528#endif 529#ifdef ETHER_8022 530 error = ef_clone(efl, ETHER_FT_8022); 531 if (error) break; 532#endif 533#ifdef ETHER_SNAP 534 error = ef_clone(efl, ETHER_FT_SNAP); 535 if (error) break; 536#endif 537 efcount++; 538 SLIST_INSERT_HEAD(&efdev, efl, el_next); 539 } 540 IFNET_RUNLOCK(); 541 if (error) { 542 if (efl) 543 SLIST_INSERT_HEAD(&efdev, efl, el_next); 544 SLIST_FOREACH(efl, &efdev, el_next) { 545 for (d = 0; d < EF_NFT; d++) 546 if (efl->el_units[d]) 547 free(efl->el_units[d], M_IFADDR); 548 free(efl, M_IFADDR); 549 } 550 return error; 551 } 552 SLIST_FOREACH(efl, &efdev, el_next) { 553 for (d = 0; d < EF_NFT; d++) { 554 efp = efl->el_units[d]; 555 if (efp) 556 ef_attach(efp); 557 } 558 } 559 ef_inputp = ef_input; 560 ef_outputp = ef_output; 561 EFDEBUG("Loaded\n"); 562 return 0; 563} 564 565static int 566ef_unload(void) 567{ 568 struct efnet *efp; 569 struct ef_link *efl; 570 int d; 571 572 ef_inputp = NULL; 573 ef_outputp = NULL; 574 SLIST_FOREACH(efl, &efdev, el_next) { 575 for (d = 0; d < EF_NFT; d++) { 576 efp = efl->el_units[d]; 577 if (efp) { 578 ef_detach(efp); 579 } 580 } 581 } 582 EFDEBUG("Unloaded\n"); 583 return 0; 584} 585 586static int 587if_ef_modevent(module_t mod, int type, void *data) 588{ 589 switch ((modeventtype_t)type) { 590 case MOD_LOAD: 591 return ef_load(); 592 case MOD_UNLOAD: 593 return ef_unload(); 594 default: 595 break; 596 } 597 return 0; 598} 599 600static moduledata_t if_ef_mod = { 601 "if_ef", if_ef_modevent, NULL 602}; 603 604DECLARE_MODULE(if_ef, if_ef_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
|