home *** CD-ROM | disk | FTP | other *** search
- /*
- * This kld gives you an example of how you can modify
- * the output function of an Ethernet Interface....
- *
- *
- * Note: Don't use it for loopback, ppp or other no eth interfaces !
- *
- * pigpen [pigpen@s0ftpj.org, deadhead@sikurezza.org]
- *
- * SoftProject NoProfit
- * Italian Security Organization
- * www.s0ftpj.org
- *
- * Sikurezza.org
- * Italian Security MailingList
- * www.sikurezza.org
- *
- */
-
- /*
- * pay attention... this kld can change in future...
- *
- * uname -a
- *
- * FreeBSD storpio.cameretta.pig 4.0-19990705-CURRENT FreeBSD 4.0-19990705-
- * CURRENT #4 ..... i386
- *
- * If you wanna a porting of this code and you have no time to do that
- * write me at: deadhead@sikurezza.org with subject "PORTING A KLD"
- *
- */
-
- #define INTERFACE "ed"
- #define INTERFACE_NUM 0
-
-
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/malloc.h>
- #include <sys/mbuf.h>
- #include <sys/kernel.h>
- #include <sys/proc.h>
- #include <sys/socket.h>
- #include <sys/socketvar.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #include <netinet/in_systm.h>
- #include <netinet/ip.h>
- #include <netinet/ip_var.h>
-
- #include <net/netisr.h>
- #include <net/route.h>
- #include <net/if_types.h>
-
- #include <netinet/in_var.h>
- #include <netinet/if_ether.h>
-
-
-
-
- #define IFP2AC(IFP) ((struct arpcom *) IFP)
- #define senderr(e) do { error = (e); goto bad;} while (0)
-
- int my_eth_output __P((register struct ifnet *,
- struct mbuf *, struct sockaddr *,
- struct rtentry *));
-
- static int module_handler __P((struct module *, int, void *));
-
- /*
- * Ethernet output routine.
- * Encapsulate a packet of type family for the local net.
- * Use trailer local net encapsulation if enough data in first
- * packet leaves a multiple of 512 bytes of data in remainder.
- * Assumes that ifp is actually pointer to arpcom structure.
- */
- int
- my_eth_output(ifp, m0, dst, rt0)
- register struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
- struct rtentry *rt0;
- {
- short type;
- int s, error = 0;
- u_char edst[6];
- register struct mbuf *m = m0;
- register struct rtentry *rt;
- register struct ether_header *eh;
- int off, len = m->m_pkthdr.len, loop_copy = 0;
- int hlen; /* link layer header lenght */
- struct arpcom *ac = IFP2AC(ifp);
-
-
- if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
- senderr(ENETDOWN);
- rt = rt0;
- if (rt) {
- if ((rt->rt_flags & RTF_UP) == 0) {
- rt0 = rt = rtalloc1(dst, 1, 0UL);
- if (rt0)
- rt->rt_refcnt--;
- else
- senderr(EHOSTUNREACH);
- }
- if (rt->rt_flags & RTF_GATEWAY) {
- if (rt->rt_gwroute == 0)
- goto lookup;
- if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) {
- rtfree(rt); rt = rt0;
- lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1,
- 0UL);
- if ((rt = rt->rt_gwroute) == 0)
- senderr(EHOSTUNREACH);
- }
- }
- if (rt->rt_flags & RTF_REJECT)
- if (rt->rt_rmx.rmx_expire == 0 ||
- time_second < rt->rt_rmx.rmx_expire)
- senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH);
- }
- hlen = ETHER_HDR_LEN;
- switch (dst->sa_family) {
- case AF_INET:
- if (!arpresolve(ac, rt, m, dst, edst, rt0))
- return (0); /* if not yet resolved */
- off = m->m_pkthdr.len - m->m_len;
- type = htons(ETHERTYPE_IP);
- break;
- case AF_UNSPEC:
- loop_copy = -1; /* if this is for us, don't do it */
- eh = (struct ether_header *)dst->sa_data;
- (void)memcpy(edst, eh->ether_dhost, sizeof (edst));
- type = eh->ether_type;
- break;
-
- default:
- printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
- dst->sa_family);
- senderr(EAFNOSUPPORT);
- }
-
- /*
- * Add local net header. If no space in first mbuf,
- * allocate another.
- */
- M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
- if (m == 0)
- senderr(ENOBUFS);
- eh = mtod(m, struct ether_header *);
- (void)memcpy(&eh->ether_type, &type,
- sizeof(eh->ether_type));
- (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
- (void)memcpy(eh->ether_shost, ac->ac_enaddr,
- sizeof(eh->ether_shost));
-
- /*
- * If a simplex interface, and the packet is being sent to our
- * Ethernet address or a broadcast address, loopback a copy.
- * XXX To make a simplex device behave exactly like a duplex
- * device, we should copy in the case of sending to our own
- * ethernet address (thus letting the original actually appear
- * on the wire). However, we don't do that here for security
- * reasons and compatibility with the original behavior.
- */
- if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) {
- if ((m->m_flags & M_BCAST) || (loop_copy > 0)) {
- struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
-
- (void) if_simloop(ifp, n, dst, hlen);
- } else if (bcmp(eh->ether_dhost,
- eh->ether_shost, ETHER_ADDR_LEN) == 0) {
- (void) if_simloop(ifp, m, dst, hlen);
- return (0); /* XXX */
- }
- }
- /*#ifdef BRIDGE
- if (do_bridge) {
- struct mbuf *m0 = m ;
-
- if (m->m_pkthdr.rcvif)
- m->m_pkthdr.rcvif = NULL ;
- ifp = bridge_dst_lookup(m);
- bdg_forward(&m0, ifp);
- if (m0)
- m_freem(m0);
- return (0);
- }
- #endif*/
- s = splimp();
- /*
- * Queue message on interface, and start output if interface
- * not yet active.
- */
- if (IF_QFULL(&ifp->if_snd)) {
- IF_DROP(&ifp->if_snd);
- splx(s);
- senderr(ENOBUFS);
- }
- IF_ENQUEUE(&ifp->if_snd, m);
- if ((ifp->if_flags & IFF_OACTIVE) == 0)
- (*ifp->if_start)(ifp);
- splx(s);
- ifp->if_obytes += len + sizeof (struct ether_header);
- if (m->m_flags & M_MCAST)
- ifp->if_omcasts++;
- return (error);
-
- bad:
- if (m)
- m_freem(m);
- return (error);
- }
-
-
-
- static int
- module_handler(struct module *module, int cmd, void *arg) {
- int s;
- struct ifnet *ifp;
-
- switch(cmd) {
- case MOD_LOAD:
- s = splimp();
- for(ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
- /* pig: sys/queue.h-> TAILQ_FOREACH(ifp, &ifnet, if_link) */
- printf("%s%d -> ", ifp->if_name, ifp->if_unit);
- if(!strcmp(ifp->if_name,INTERFACE) &&
- ifp->if_unit == INTERFACE_NUM) {
- ifp->if_output = my_eth_output;
- printf("MODIFIED");
- } else
- printf("no");
- printf("\n");
- }
- splx(s);
- break;
-
- case MOD_UNLOAD:
- s = splimp();
- for(ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {
- if( !strcmp(ifp->if_name,INTERFACE) &&
- ifp->if_unit == INTERFACE_NUM) {
- ifp->if_output = ether_output;
- printf("%s%d output funct: Updated\n",ifp->if_name,
- ifp->if_unit);
- }
- }
- splx(s);
- break;
- }
-
- return 0;
- }
-
- static moduledata_t mymod = {
- "eth_out",
- module_handler,
- 0
- };
-
- DECLARE_MODULE(eth_out, mymod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-