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 154518 2006-01-18 14:24:39Z andre $
| 26 * $FreeBSD: head/sys/net/if_ef.c 177599 2008-03-25 09:39:02Z ru $
|
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/* If none of the supported layers is enabled explicitly enable them all */ 65#if !defined(ETHER_II) && !defined(ETHER_8023) && !defined(ETHER_8022) && \ 66 !defined(ETHER_SNAP) 67#define ETHER_II 1 68#define ETHER_8023 1 69#define ETHER_8022 1 70#define ETHER_SNAP 1 71#endif 72 73/* internal frame types */ 74#define ETHER_FT_EII 0 /* Ethernet_II - default */ 75#define ETHER_FT_8023 1 /* 802.3 (Novell) */ 76#define ETHER_FT_8022 2 /* 802.2 */ 77#define ETHER_FT_SNAP 3 /* SNAP */ 78#define EF_NFT 4 /* total number of frame types */ 79 80#ifdef EF_DEBUG 81#define EFDEBUG(format, args...) printf("%s: "format, __func__ ,## args) 82#else 83#define EFDEBUG(format, args...) 84#endif 85 86#define EFERROR(format, args...) printf("%s: "format, __func__ ,## args) 87 88struct efnet { 89 struct ifnet *ef_ifp; 90 struct ifnet *ef_pifp; 91 int ef_frametype; 92}; 93 94struct ef_link { 95 SLIST_ENTRY(ef_link) el_next; 96 struct ifnet *el_ifp; /* raw device for this clones */ 97 struct efnet *el_units[EF_NFT]; /* our clones */ 98}; 99 100static SLIST_HEAD(ef_link_head, ef_link) efdev = {NULL}; 101static int efcount; 102 103extern int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 104extern int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 105 struct sockaddr *dst, short *tp, int *hlen); 106 107/* 108static void ef_reset (struct ifnet *); 109*/ 110static int ef_attach(struct efnet *sc); 111static int ef_detach(struct efnet *sc); 112static void ef_init(void *); 113static int ef_ioctl(struct ifnet *, u_long, caddr_t); 114static void ef_start(struct ifnet *); 115static int ef_input(struct ifnet*, struct ether_header *, struct mbuf *); 116static int ef_output(struct ifnet *ifp, struct mbuf **mp, 117 struct sockaddr *dst, short *tp, int *hlen); 118 119static int ef_load(void); 120static int ef_unload(void); 121 122/* 123 * Install the interface, most of structure initialization done in ef_clone() 124 */ 125static int 126ef_attach(struct efnet *sc) 127{ 128 struct ifnet *ifp = sc->ef_ifp; 129 130 ifp->if_start = ef_start; 131 ifp->if_watchdog = NULL; 132 ifp->if_init = ef_init; 133 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 134 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 135 /* 136 * Attach the interface 137 */ 138 ether_ifattach(ifp, IF_LLADDR(sc->ef_pifp)); 139 140 ifp->if_resolvemulti = 0; 141 ifp->if_type = IFT_XETHER; 142 ifp->if_drv_flags |= IFF_DRV_RUNNING; 143 144 EFDEBUG("%s: attached\n", ifp->if_xname); 145 return 1; 146} 147 148/* 149 * This is for _testing_only_, just removes interface from interfaces list 150 */ 151static int 152ef_detach(struct efnet *sc) 153{ 154 struct ifnet *ifp = sc->ef_ifp; 155 int s; 156 157 s = splimp(); 158 159 ether_ifdetach(ifp); 160 if_free(ifp); 161 162 splx(s); 163 return 0; 164} 165 166static void 167ef_init(void *foo) { 168 return; 169} 170 171static int 172ef_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 173{ 174 struct efnet *sc = ifp->if_softc; 175 struct ifaddr *ifa = (struct ifaddr*)data; 176 int s, error; 177 178 EFDEBUG("IOCTL %ld for %s\n", cmd, ifp->if_xname); 179 error = 0; 180 s = splimp(); 181 switch (cmd) { 182 case SIOCSIFFLAGS: 183 error = 0; 184 break; 185 case SIOCSIFADDR: 186 if (sc->ef_frametype == ETHER_FT_8023 && 187 ifa->ifa_addr->sa_family != AF_IPX) { 188 error = EAFNOSUPPORT; 189 break; 190 } 191 ifp->if_flags |= IFF_UP; 192 /* FALL THROUGH */ 193 default: 194 error = ether_ioctl(ifp, cmd, data); 195 break; 196 } 197 splx(s); 198 return error; 199} 200 201/* 202 * Currently packet prepared in the ether_output(), but this can be a better 203 * place. 204 */ 205static void 206ef_start(struct ifnet *ifp) 207{ 208 struct efnet *sc = (struct efnet*)ifp->if_softc; 209 struct ifnet *p; 210 struct mbuf *m; 211 int error; 212 213 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 214 p = sc->ef_pifp; 215 216 EFDEBUG("\n"); 217 for (;;) { 218 IF_DEQUEUE(&ifp->if_snd, m); 219 if (m == 0) 220 break; 221 BPF_MTAP(ifp, m); 222 IFQ_HANDOFF(p, m, error); 223 if (error) { 224 ifp->if_oerrors++; 225 continue; 226 } 227 ifp->if_opackets++; 228 } 229 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 230 return; 231} 232 233/* 234 * Inline functions do not put additional overhead to procedure call or 235 * parameter passing but simplify the code 236 */ 237static int __inline 238ef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type) 239{ 240 int isr; 241 242 switch(ether_type) { 243#ifdef IPX 244 case ETHERTYPE_IPX: 245 isr = NETISR_IPX; 246 break; 247#endif 248#ifdef INET 249 case ETHERTYPE_IP: 250 if ((m = ip_fastforward(m)) == NULL) 251 return (0); 252 isr = NETISR_IP; 253 break; 254 255 case ETHERTYPE_ARP: 256 isr = NETISR_ARP; 257 break; 258#endif 259 default: 260 return (EPROTONOSUPPORT); 261 } 262 netisr_dispatch(isr, m); 263 return (0); 264} 265 266static int __inline 267ef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l, 268 u_short ether_type) 269{ 270 int isr; 271 272 switch(ether_type) { 273#ifdef IPX 274 case ETHERTYPE_IPX: 275 m_adj(m, 8); 276 isr = NETISR_IPX; 277 break; 278#endif 279 default: 280 return (EPROTONOSUPPORT); 281 } 282 netisr_dispatch(isr, m); 283 return (0); 284} 285 286static int __inline 287ef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l, 288 u_short ether_type) 289{ 290 int isr; 291 292 switch(ether_type) { 293#ifdef IPX 294 case 0xe0: 295 m_adj(m, 3); 296 isr = NETISR_IPX; 297 break; 298#endif 299 default: 300 return (EPROTONOSUPPORT); 301 } 302 netisr_dispatch(isr, m); 303 return (0); 304} 305 306/* 307 * Called from ether_input() 308 */ 309static int 310ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) 311{ 312 u_short ether_type; 313 int ft = -1; 314 struct efnet *efp; 315 struct ifnet *eifp; 316 struct llc *l; 317 struct ef_link *efl; 318 int isr; 319 320 ether_type = ntohs(eh->ether_type); 321 l = NULL; 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_ifp; 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 BPF_MTAP2(eifp, eh, ETHER_HDR_LEN, m); 371 /* 372 * Now we ready to adjust mbufs and pass them to protocol intr's 373 */ 374 switch(ft) { 375 case ETHER_FT_EII: 376 return (ef_inputEII(m, eh, ether_type)); 377#ifdef IPX 378 case ETHER_FT_8023: /* only IPX can be here */ 379 isr = NETISR_IPX; 380 break; 381#endif 382 case ETHER_FT_SNAP: 383 return (ef_inputSNAP(m, eh, l, ether_type)); 384 case ETHER_FT_8022: 385 return (ef_input8022(m, eh, l, ether_type)); 386 default: 387 EFDEBUG("No support for frame %d and proto %04x\n", 388 ft, ether_type); 389 return (EPROTONOSUPPORT); 390 } 391 netisr_dispatch(isr, m); 392 return (0); 393} 394 395static int 396ef_output(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, short *tp, 397 int *hlen) 398{ 399 struct efnet *sc = (struct efnet*)ifp->if_softc; 400 struct mbuf *m = *mp; 401 u_char *cp; 402 short type; 403 404 if (ifp->if_type != IFT_XETHER) 405 return ENETDOWN; 406 switch (sc->ef_frametype) { 407 case ETHER_FT_EII: 408#ifdef IPX 409 type = htons(ETHERTYPE_IPX); 410#else 411 return EPFNOSUPPORT; 412#endif 413 break; 414 case ETHER_FT_8023: 415 type = htons(m->m_pkthdr.len); 416 break; 417 case ETHER_FT_8022:
| 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/* If none of the supported layers is enabled explicitly enable them all */ 65#if !defined(ETHER_II) && !defined(ETHER_8023) && !defined(ETHER_8022) && \ 66 !defined(ETHER_SNAP) 67#define ETHER_II 1 68#define ETHER_8023 1 69#define ETHER_8022 1 70#define ETHER_SNAP 1 71#endif 72 73/* internal frame types */ 74#define ETHER_FT_EII 0 /* Ethernet_II - default */ 75#define ETHER_FT_8023 1 /* 802.3 (Novell) */ 76#define ETHER_FT_8022 2 /* 802.2 */ 77#define ETHER_FT_SNAP 3 /* SNAP */ 78#define EF_NFT 4 /* total number of frame types */ 79 80#ifdef EF_DEBUG 81#define EFDEBUG(format, args...) printf("%s: "format, __func__ ,## args) 82#else 83#define EFDEBUG(format, args...) 84#endif 85 86#define EFERROR(format, args...) printf("%s: "format, __func__ ,## args) 87 88struct efnet { 89 struct ifnet *ef_ifp; 90 struct ifnet *ef_pifp; 91 int ef_frametype; 92}; 93 94struct ef_link { 95 SLIST_ENTRY(ef_link) el_next; 96 struct ifnet *el_ifp; /* raw device for this clones */ 97 struct efnet *el_units[EF_NFT]; /* our clones */ 98}; 99 100static SLIST_HEAD(ef_link_head, ef_link) efdev = {NULL}; 101static int efcount; 102 103extern int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 104extern int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 105 struct sockaddr *dst, short *tp, int *hlen); 106 107/* 108static void ef_reset (struct ifnet *); 109*/ 110static int ef_attach(struct efnet *sc); 111static int ef_detach(struct efnet *sc); 112static void ef_init(void *); 113static int ef_ioctl(struct ifnet *, u_long, caddr_t); 114static void ef_start(struct ifnet *); 115static int ef_input(struct ifnet*, struct ether_header *, struct mbuf *); 116static int ef_output(struct ifnet *ifp, struct mbuf **mp, 117 struct sockaddr *dst, short *tp, int *hlen); 118 119static int ef_load(void); 120static int ef_unload(void); 121 122/* 123 * Install the interface, most of structure initialization done in ef_clone() 124 */ 125static int 126ef_attach(struct efnet *sc) 127{ 128 struct ifnet *ifp = sc->ef_ifp; 129 130 ifp->if_start = ef_start; 131 ifp->if_watchdog = NULL; 132 ifp->if_init = ef_init; 133 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 134 ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); 135 /* 136 * Attach the interface 137 */ 138 ether_ifattach(ifp, IF_LLADDR(sc->ef_pifp)); 139 140 ifp->if_resolvemulti = 0; 141 ifp->if_type = IFT_XETHER; 142 ifp->if_drv_flags |= IFF_DRV_RUNNING; 143 144 EFDEBUG("%s: attached\n", ifp->if_xname); 145 return 1; 146} 147 148/* 149 * This is for _testing_only_, just removes interface from interfaces list 150 */ 151static int 152ef_detach(struct efnet *sc) 153{ 154 struct ifnet *ifp = sc->ef_ifp; 155 int s; 156 157 s = splimp(); 158 159 ether_ifdetach(ifp); 160 if_free(ifp); 161 162 splx(s); 163 return 0; 164} 165 166static void 167ef_init(void *foo) { 168 return; 169} 170 171static int 172ef_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 173{ 174 struct efnet *sc = ifp->if_softc; 175 struct ifaddr *ifa = (struct ifaddr*)data; 176 int s, error; 177 178 EFDEBUG("IOCTL %ld for %s\n", cmd, ifp->if_xname); 179 error = 0; 180 s = splimp(); 181 switch (cmd) { 182 case SIOCSIFFLAGS: 183 error = 0; 184 break; 185 case SIOCSIFADDR: 186 if (sc->ef_frametype == ETHER_FT_8023 && 187 ifa->ifa_addr->sa_family != AF_IPX) { 188 error = EAFNOSUPPORT; 189 break; 190 } 191 ifp->if_flags |= IFF_UP; 192 /* FALL THROUGH */ 193 default: 194 error = ether_ioctl(ifp, cmd, data); 195 break; 196 } 197 splx(s); 198 return error; 199} 200 201/* 202 * Currently packet prepared in the ether_output(), but this can be a better 203 * place. 204 */ 205static void 206ef_start(struct ifnet *ifp) 207{ 208 struct efnet *sc = (struct efnet*)ifp->if_softc; 209 struct ifnet *p; 210 struct mbuf *m; 211 int error; 212 213 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 214 p = sc->ef_pifp; 215 216 EFDEBUG("\n"); 217 for (;;) { 218 IF_DEQUEUE(&ifp->if_snd, m); 219 if (m == 0) 220 break; 221 BPF_MTAP(ifp, m); 222 IFQ_HANDOFF(p, m, error); 223 if (error) { 224 ifp->if_oerrors++; 225 continue; 226 } 227 ifp->if_opackets++; 228 } 229 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 230 return; 231} 232 233/* 234 * Inline functions do not put additional overhead to procedure call or 235 * parameter passing but simplify the code 236 */ 237static int __inline 238ef_inputEII(struct mbuf *m, struct ether_header *eh, u_short ether_type) 239{ 240 int isr; 241 242 switch(ether_type) { 243#ifdef IPX 244 case ETHERTYPE_IPX: 245 isr = NETISR_IPX; 246 break; 247#endif 248#ifdef INET 249 case ETHERTYPE_IP: 250 if ((m = ip_fastforward(m)) == NULL) 251 return (0); 252 isr = NETISR_IP; 253 break; 254 255 case ETHERTYPE_ARP: 256 isr = NETISR_ARP; 257 break; 258#endif 259 default: 260 return (EPROTONOSUPPORT); 261 } 262 netisr_dispatch(isr, m); 263 return (0); 264} 265 266static int __inline 267ef_inputSNAP(struct mbuf *m, struct ether_header *eh, struct llc* l, 268 u_short ether_type) 269{ 270 int isr; 271 272 switch(ether_type) { 273#ifdef IPX 274 case ETHERTYPE_IPX: 275 m_adj(m, 8); 276 isr = NETISR_IPX; 277 break; 278#endif 279 default: 280 return (EPROTONOSUPPORT); 281 } 282 netisr_dispatch(isr, m); 283 return (0); 284} 285 286static int __inline 287ef_input8022(struct mbuf *m, struct ether_header *eh, struct llc* l, 288 u_short ether_type) 289{ 290 int isr; 291 292 switch(ether_type) { 293#ifdef IPX 294 case 0xe0: 295 m_adj(m, 3); 296 isr = NETISR_IPX; 297 break; 298#endif 299 default: 300 return (EPROTONOSUPPORT); 301 } 302 netisr_dispatch(isr, m); 303 return (0); 304} 305 306/* 307 * Called from ether_input() 308 */ 309static int 310ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) 311{ 312 u_short ether_type; 313 int ft = -1; 314 struct efnet *efp; 315 struct ifnet *eifp; 316 struct llc *l; 317 struct ef_link *efl; 318 int isr; 319 320 ether_type = ntohs(eh->ether_type); 321 l = NULL; 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_ifp; 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 BPF_MTAP2(eifp, eh, ETHER_HDR_LEN, m); 371 /* 372 * Now we ready to adjust mbufs and pass them to protocol intr's 373 */ 374 switch(ft) { 375 case ETHER_FT_EII: 376 return (ef_inputEII(m, eh, ether_type)); 377#ifdef IPX 378 case ETHER_FT_8023: /* only IPX can be here */ 379 isr = NETISR_IPX; 380 break; 381#endif 382 case ETHER_FT_SNAP: 383 return (ef_inputSNAP(m, eh, l, ether_type)); 384 case ETHER_FT_8022: 385 return (ef_input8022(m, eh, l, ether_type)); 386 default: 387 EFDEBUG("No support for frame %d and proto %04x\n", 388 ft, ether_type); 389 return (EPROTONOSUPPORT); 390 } 391 netisr_dispatch(isr, m); 392 return (0); 393} 394 395static int 396ef_output(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst, short *tp, 397 int *hlen) 398{ 399 struct efnet *sc = (struct efnet*)ifp->if_softc; 400 struct mbuf *m = *mp; 401 u_char *cp; 402 short type; 403 404 if (ifp->if_type != IFT_XETHER) 405 return ENETDOWN; 406 switch (sc->ef_frametype) { 407 case ETHER_FT_EII: 408#ifdef IPX 409 type = htons(ETHERTYPE_IPX); 410#else 411 return EPFNOSUPPORT; 412#endif 413 break; 414 case ETHER_FT_8023: 415 type = htons(m->m_pkthdr.len); 416 break; 417 case ETHER_FT_8022:
|
418 M_PREPEND(m, ETHER_HDR_LEN + 3, M_TRYWAIT); 419 if (m == NULL) { 420 *mp = NULL; 421 return ENOBUFS; 422 }
| 418 M_PREPEND(m, ETHER_HDR_LEN + 3, M_WAIT);
|
423 /* 424 * Ensure that ethernet header and next three bytes 425 * will fit into single mbuf 426 */ 427 m = m_pullup(m, ETHER_HDR_LEN + 3); 428 if (m == NULL) { 429 *mp = NULL; 430 return ENOBUFS; 431 } 432 m_adj(m, ETHER_HDR_LEN); 433 type = htons(m->m_pkthdr.len); 434 cp = mtod(m, u_char *); 435 *cp++ = 0xE0; 436 *cp++ = 0xE0; 437 *cp++ = 0x03; 438 *hlen += 3; 439 break; 440 case ETHER_FT_SNAP:
| 419 /* 420 * Ensure that ethernet header and next three bytes 421 * will fit into single mbuf 422 */ 423 m = m_pullup(m, ETHER_HDR_LEN + 3); 424 if (m == NULL) { 425 *mp = NULL; 426 return ENOBUFS; 427 } 428 m_adj(m, ETHER_HDR_LEN); 429 type = htons(m->m_pkthdr.len); 430 cp = mtod(m, u_char *); 431 *cp++ = 0xE0; 432 *cp++ = 0xE0; 433 *cp++ = 0x03; 434 *hlen += 3; 435 break; 436 case ETHER_FT_SNAP:
|
441 M_PREPEND(m, 8, M_TRYWAIT); 442 if (m == NULL) { 443 *mp = NULL; 444 return ENOBUFS; 445 }
| 437 M_PREPEND(m, 8, M_WAIT);
|
446 type = htons(m->m_pkthdr.len); 447 cp = mtod(m, u_char *); 448 bcopy("\xAA\xAA\x03\x00\x00\x00\x81\x37", cp, 8); 449 *hlen += 8; 450 break; 451 default: 452 return EPFNOSUPPORT; 453 } 454 *mp = m; 455 *tp = type; 456 return 0; 457} 458 459/* 460 * Create clone from the given interface 461 */ 462static int 463ef_clone(struct ef_link *efl, int ft) 464{ 465 struct efnet *efp; 466 struct ifnet *eifp; 467 struct ifnet *ifp = efl->el_ifp; 468 469 efp = (struct efnet*)malloc(sizeof(struct efnet), M_IFADDR, 470 M_WAITOK | M_ZERO); 471 if (efp == NULL) 472 return ENOMEM; 473 efp->ef_pifp = ifp; 474 efp->ef_frametype = ft; 475 eifp = efp->ef_ifp = if_alloc(IFT_ETHER); 476 if (eifp == NULL) { 477 free(efp, M_IFADDR); 478 return (ENOSPC); 479 } 480 snprintf(eifp->if_xname, IFNAMSIZ, 481 "%sf%d", ifp->if_xname, efp->ef_frametype); 482 eifp->if_dname = "ef"; 483 eifp->if_dunit = IF_DUNIT_NONE; 484 eifp->if_softc = efp; 485 if (ifp->if_ioctl) 486 eifp->if_ioctl = ef_ioctl; 487 efl->el_units[ft] = efp; 488 return 0; 489} 490 491static int 492ef_load(void) 493{ 494 struct ifnet *ifp; 495 struct efnet *efp; 496 struct ef_link *efl = NULL, *efl_temp; 497 int error = 0, d; 498 499 IFNET_RLOCK(); 500 TAILQ_FOREACH(ifp, &ifnet, if_link) { 501 if (ifp->if_type != IFT_ETHER) continue; 502 EFDEBUG("Found interface %s\n", ifp->if_xname); 503 efl = (struct ef_link*)malloc(sizeof(struct ef_link), 504 M_IFADDR, M_WAITOK | M_ZERO); 505 if (efl == NULL) { 506 error = ENOMEM; 507 break; 508 } 509 510 efl->el_ifp = ifp; 511#ifdef ETHER_II 512 error = ef_clone(efl, ETHER_FT_EII); 513 if (error) break; 514#endif 515#ifdef ETHER_8023 516 error = ef_clone(efl, ETHER_FT_8023); 517 if (error) break; 518#endif 519#ifdef ETHER_8022 520 error = ef_clone(efl, ETHER_FT_8022); 521 if (error) break; 522#endif 523#ifdef ETHER_SNAP 524 error = ef_clone(efl, ETHER_FT_SNAP); 525 if (error) break; 526#endif 527 efcount++; 528 SLIST_INSERT_HEAD(&efdev, efl, el_next); 529 } 530 IFNET_RUNLOCK(); 531 if (error) { 532 if (efl) 533 SLIST_INSERT_HEAD(&efdev, efl, el_next); 534 SLIST_FOREACH_SAFE(efl, &efdev, el_next, efl_temp) { 535 for (d = 0; d < EF_NFT; d++) 536 if (efl->el_units[d]) { 537 if (efl->el_units[d]->ef_pifp != NULL) 538 if_free(efl->el_units[d]->ef_pifp); 539 free(efl->el_units[d], M_IFADDR); 540 } 541 free(efl, M_IFADDR); 542 } 543 return error; 544 } 545 SLIST_FOREACH(efl, &efdev, el_next) { 546 for (d = 0; d < EF_NFT; d++) { 547 efp = efl->el_units[d]; 548 if (efp) 549 ef_attach(efp); 550 } 551 } 552 ef_inputp = ef_input; 553 ef_outputp = ef_output; 554 EFDEBUG("Loaded\n"); 555 return 0; 556} 557 558static int 559ef_unload(void) 560{ 561 struct efnet *efp; 562 struct ef_link *efl; 563 int d; 564 565 ef_inputp = NULL; 566 ef_outputp = NULL; 567 SLIST_FOREACH(efl, &efdev, el_next) { 568 for (d = 0; d < EF_NFT; d++) { 569 efp = efl->el_units[d]; 570 if (efp) { 571 ef_detach(efp); 572 } 573 } 574 } 575 EFDEBUG("Unloaded\n"); 576 return 0; 577} 578 579static int 580if_ef_modevent(module_t mod, int type, void *data) 581{ 582 switch ((modeventtype_t)type) { 583 case MOD_LOAD: 584 return ef_load(); 585 case MOD_UNLOAD: 586 return ef_unload(); 587 default: 588 return EOPNOTSUPP; 589 } 590 return 0; 591} 592 593static moduledata_t if_ef_mod = { 594 "if_ef", if_ef_modevent, NULL 595}; 596 597DECLARE_MODULE(if_ef, if_ef_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
| 438 type = htons(m->m_pkthdr.len); 439 cp = mtod(m, u_char *); 440 bcopy("\xAA\xAA\x03\x00\x00\x00\x81\x37", cp, 8); 441 *hlen += 8; 442 break; 443 default: 444 return EPFNOSUPPORT; 445 } 446 *mp = m; 447 *tp = type; 448 return 0; 449} 450 451/* 452 * Create clone from the given interface 453 */ 454static int 455ef_clone(struct ef_link *efl, int ft) 456{ 457 struct efnet *efp; 458 struct ifnet *eifp; 459 struct ifnet *ifp = efl->el_ifp; 460 461 efp = (struct efnet*)malloc(sizeof(struct efnet), M_IFADDR, 462 M_WAITOK | M_ZERO); 463 if (efp == NULL) 464 return ENOMEM; 465 efp->ef_pifp = ifp; 466 efp->ef_frametype = ft; 467 eifp = efp->ef_ifp = if_alloc(IFT_ETHER); 468 if (eifp == NULL) { 469 free(efp, M_IFADDR); 470 return (ENOSPC); 471 } 472 snprintf(eifp->if_xname, IFNAMSIZ, 473 "%sf%d", ifp->if_xname, efp->ef_frametype); 474 eifp->if_dname = "ef"; 475 eifp->if_dunit = IF_DUNIT_NONE; 476 eifp->if_softc = efp; 477 if (ifp->if_ioctl) 478 eifp->if_ioctl = ef_ioctl; 479 efl->el_units[ft] = efp; 480 return 0; 481} 482 483static int 484ef_load(void) 485{ 486 struct ifnet *ifp; 487 struct efnet *efp; 488 struct ef_link *efl = NULL, *efl_temp; 489 int error = 0, d; 490 491 IFNET_RLOCK(); 492 TAILQ_FOREACH(ifp, &ifnet, if_link) { 493 if (ifp->if_type != IFT_ETHER) continue; 494 EFDEBUG("Found interface %s\n", ifp->if_xname); 495 efl = (struct ef_link*)malloc(sizeof(struct ef_link), 496 M_IFADDR, M_WAITOK | M_ZERO); 497 if (efl == NULL) { 498 error = ENOMEM; 499 break; 500 } 501 502 efl->el_ifp = ifp; 503#ifdef ETHER_II 504 error = ef_clone(efl, ETHER_FT_EII); 505 if (error) break; 506#endif 507#ifdef ETHER_8023 508 error = ef_clone(efl, ETHER_FT_8023); 509 if (error) break; 510#endif 511#ifdef ETHER_8022 512 error = ef_clone(efl, ETHER_FT_8022); 513 if (error) break; 514#endif 515#ifdef ETHER_SNAP 516 error = ef_clone(efl, ETHER_FT_SNAP); 517 if (error) break; 518#endif 519 efcount++; 520 SLIST_INSERT_HEAD(&efdev, efl, el_next); 521 } 522 IFNET_RUNLOCK(); 523 if (error) { 524 if (efl) 525 SLIST_INSERT_HEAD(&efdev, efl, el_next); 526 SLIST_FOREACH_SAFE(efl, &efdev, el_next, efl_temp) { 527 for (d = 0; d < EF_NFT; d++) 528 if (efl->el_units[d]) { 529 if (efl->el_units[d]->ef_pifp != NULL) 530 if_free(efl->el_units[d]->ef_pifp); 531 free(efl->el_units[d], M_IFADDR); 532 } 533 free(efl, M_IFADDR); 534 } 535 return error; 536 } 537 SLIST_FOREACH(efl, &efdev, el_next) { 538 for (d = 0; d < EF_NFT; d++) { 539 efp = efl->el_units[d]; 540 if (efp) 541 ef_attach(efp); 542 } 543 } 544 ef_inputp = ef_input; 545 ef_outputp = ef_output; 546 EFDEBUG("Loaded\n"); 547 return 0; 548} 549 550static int 551ef_unload(void) 552{ 553 struct efnet *efp; 554 struct ef_link *efl; 555 int d; 556 557 ef_inputp = NULL; 558 ef_outputp = NULL; 559 SLIST_FOREACH(efl, &efdev, el_next) { 560 for (d = 0; d < EF_NFT; d++) { 561 efp = efl->el_units[d]; 562 if (efp) { 563 ef_detach(efp); 564 } 565 } 566 } 567 EFDEBUG("Unloaded\n"); 568 return 0; 569} 570 571static int 572if_ef_modevent(module_t mod, int type, void *data) 573{ 574 switch ((modeventtype_t)type) { 575 case MOD_LOAD: 576 return ef_load(); 577 case MOD_UNLOAD: 578 return ef_unload(); 579 default: 580 return EOPNOTSUPP; 581 } 582 return 0; 583} 584 585static moduledata_t if_ef_mod = { 586 "if_ef", if_ef_modevent, NULL 587}; 588 589DECLARE_MODULE(if_ef, if_ef_mod, SI_SUB_PSEUDO, SI_ORDER_MIDDLE);
|