Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/kernel.h>
- #include <sys/mbuf.h>
- #include <sys/module.h>
- #include <machine/bus.h>
- #include <sys/rman.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>
- #include <sys/sysctl.h>
- #include <net/if.h>
- #include <net/if_clone.h>
- #include <net/if_types.h>
- #include <net/netisr.h>
- #include <net/route.h>
- #include <net/bpf.h>
- #include <net/vnet.h>
- #include <net/ethernet.h>
- #ifdef INET
- #include <netinet/in.h>
- #include <netinet/in_var.h>
- #endif
- #define SMMTU (1024 + 512)
- #define SM_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)
- #define SM_CSUM_SET (CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | \
- CSUM_PSEUDO_HDR | CSUM_SCTP_VALID)
- int smioctl(struct ifnet *, u_long, caddr_t);
- static void smrtrequest(int, struct rtentry *, struct rt_addrinfo *);
- int smoutput(struct ifnet *, struct mbuf *, struct sockaddr *, struct route *);
- void loopatach(struct ifnet *, int);
- void
- loopatach(struct ifnet *ifp, int unit)
- {
- ifp = if_alloc(IFT_LOOP);
- if (ifp == NULL)
- return;
- if_initname(ifp, "sm", unit);
- ifp->if_mtu = SMMTU;
- ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
- ifp->if_ioctl = smioctl;
- ifp->if_output = smoutput;
- ifp->if_snd.ifq_maxlen = ifqmaxlen;
- ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM;
- ifp->if_hwassist = SM_CSUM_FEATURES;
- if_attach(ifp);
- bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
- }
- static void
- smrtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
- {
- RT_LOCK_ASSERT(rt);
- rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu;
- }
- int
- smioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
- {
- struct ifaddr *ifa;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, mask;
- switch (cmd) {
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifa = (struct ifaddr *)data;
- ifa->ifa_rtrequest = smrtrequest;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (ifr == 0) {
- error = EAFNOSUPPORT;
- break;
- }
- if (ifr->ifr_addr.sa_family == AF_INET)
- break;
- else {
- error = EAFNOSUPPORT;
- break;
- }
- case SIOCSIFMTU:
- ifp->if_mtu = ifr->ifr_mtu;
- break;
- case SIOCSIFFLAGS:
- break;
- case SIOCSIFCAP:
- mask = ifp->if_capenable ^ ifr->ifr_reqcap;
- if ((mask & IFCAP_RXCSUM) != 0)
- ifp->if_capenable ^= IFCAP_RXCSUM;
- if ((mask & IFCAP_TXCSUM) != 0)
- ifp->if_capenable ^= IFCAP_TXCSUM;
- ifp->if_hwassist = 0;
- if (ifp->if_capenable & IFCAP_TXCSUM)
- ifp->if_hwassist = SM_CSUM_FEATURES;
- break;
- default:
- error = EINVAL;
- }
- return (error);
- }
- int
- smoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
- struct route *ro)
- {
- u_int32_t af;
- struct rtentry *rt = NULL;
- #ifdef MAC
- int error = 0;
- #endif
- M_ASSERTPKTHDR(m);
- if (ro != NULL)
- rt = ro->ro_rt;
- #ifdef MAC
- error = mac_ifnet_check_transmit(ifp, m);
- if (error) {
- m_freem(m);
- return (error);
- }
- #endif
- if (rt && rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE)) {
- m_freem(m);
- return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
- rt->rt_flags & RTF_HOST ? EHOSTUNREACH :
- ENETUNREACH);
- }
- ifp->if_opackets++;
- ifp->if_obytes += m->m_pkthdr.len;
- if (dst->sa_family == AF_UNSPEC) {
- bcopy(dst->sa_data, &af, sizeof(af));
- dst->sa_family = af;
- }
- if (dst->sa_family == AF_INET) {
- if (ifp->if_capenable & IFCAP_RXCSUM) {
- m->m_pkthdr.csum_data = 0xffff;
- m->m_pkthdr.csum_flags = SM_CSUM_SET;
- }
- m->m_pkthdr.csum_flags &= ~ SM_CSUM_FEATURES;
- } else {
- printf("smoutput: af=%d unexpected\n", dst->sa_family);
- m_freem(m);
- return (EAFNOSUPPORT);
- }
- return (if_simloop(ifp, m, dst->sa_family, 0));
- }
- int
- if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen)
- {
- int isr, i;
- struct ether_header *eh;
- M_ASSERTPKTHDR(m);
- m_tag_delete_nonpersistent(m);
- m->m_pkthdr.rcvif = ifp;
- if (hlen > 0) {
- if (bpf_peers_present(ifp->if_bpf)){
- bpf_mtap(ifp->if_bpf, m);
- }
- } else {
- m = m_pullup(m, sizeof(*eh));
- if (m == NULL) {
- return (EINVAL);
- }
- }
- if (hlen > 0) {
- m_adj(m, hlen);
- #ifndef __NO_STRICT_ALIGNMENT
- if (mtod(m, vm_offset_t) & 3) {
- KASSERT(hlen >= 3, ("if_simloop: hlen too small"));
- bcopy(m->m_data, (char*)(mtod(m, vm_offset_t)
- - (mtod(m,vm_offset_t) & 3)),
- m->m_len);
- m->m_data -= (mtod(m, vm_offset_t) & 3);
- }
- #endif
- }
- if (af == AF_INET) {
- isr = NETISR_IP;
- } else {
- printf("if_simloop: can't handle af=%d\n", af);
- m_freem(m);
- return (EAFNOSUPPORT);
- }
- ifp->if_ipackets++;
- ifp->if_ibytes += m->m_pkthdr.len;
- netisr_queue(isr, m);
- BPF_MTAP(ifp, m);
- eh = mtod(m, struct ether_header *);
- for (i = 0; i < ETHER_ADDR_LEN; i++){
- printf("%2x", eh->ether_dhost[i]);
- printf("\t");
- printf("%2x", eh->ether_shost[i]);
- }
- return (0);
- }
- static int
- sm_modevent(module_t mod, int type, void *data)
- {
- switch (type) {
- case MOD_LOAD:
- printf("module sm loaded\n");
- break;
- case MOD_UNLOAD:
- printf("module not possible to unload\n");
- return (EINVAL);
- default:
- return (EOPNOTSUPP);
- }
- return (0);
- }
- static moduledata_t sm_mod = {
- "if_sm",
- sm_modevent,
- 0
- };
- DECLARE_MODULE(if_sm, sm_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement