The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/net/kext_net.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /* Copyright (C) 1999 Apple Computer, Inc.  */
   26 
   27 /*
   28  * Support for Network Kernel Extensions: Socket Filters
   29  *
   30  * Justin C. Walker, 990319
   31  */
   32 
   33 #include <sys/types.h>
   34 #include <sys/queue.h>
   35 #include <sys/malloc.h>
   36 #include <sys/param.h>
   37 #include <sys/mbuf.h>
   38 #include <sys/domain.h>
   39 #include <sys/protosw.h>
   40 #include <sys/socket.h>
   41 #include <machine/spl.h>
   42 #include "kext_net.h"
   43 
   44 /* List of kernel extensions (networking) known to kernel */
   45 struct nf_list nf_list;
   46 
   47 static int sockfilter_fix_symantec_bug(struct NFDescriptor* theirDesc);
   48 
   49 /*
   50  * Register a global filter for the specified protocol
   51  * Make a few checks and then insert the new descriptor in the
   52  *  filter list and, if global, in its protosw's chain.
   53  */
   54 int
   55 register_sockfilter(struct NFDescriptor *nfp, struct NFDescriptor *nfp1,
   56                     struct protosw *pr, int flags)
   57 {       int s;
   58         static int NF_initted = 0;
   59 
   60         if (nfp == NULL)
   61                 return(EINVAL);
   62 
   63         /* Fix Symantec's broken NPC kext */
   64         if (nfp->nf_handle == 0xf1ab02de) {
   65                 int err = sockfilter_fix_symantec_bug(nfp);
   66                 if (err != 0)
   67                         return err;
   68         }
   69 
   70         s = splhigh();
   71         if (!NF_initted)
   72         {       NF_initted = 1;
   73                 TAILQ_INIT(&nf_list);
   74         }
   75 
   76         /*
   77          * Install the extension:
   78          * First, put it in the global list of all filters
   79          * Then, if global, install in the protosw's list 
   80          */
   81         TAILQ_INSERT_TAIL(&nf_list, nfp, nf_list);
   82         if (nfp->nf_flags & NFD_GLOBAL)
   83         {       if (flags & NFF_BEFORE)
   84                 {       if (nfp1 == NULL)
   85                         {       TAILQ_INSERT_HEAD(&pr->pr_sfilter,
   86                                                   nfp, nf_next);
   87                         } else
   88                                 TAILQ_INSERT_BEFORE(nfp1, nfp, nf_next);
   89                 } else          /* Default: AFTER */
   90                 {       if (nfp1 == NULL)
   91                         {       TAILQ_INSERT_TAIL(&pr->pr_sfilter,
   92                                                   nfp, nf_next);
   93                         } else
   94                                 TAILQ_INSERT_AFTER(&pr->pr_sfilter, nfp1,
   95                                                    nfp, nf_next);
   96                 }
   97         }
   98         splx(s);
   99         return(0);
  100 }
  101 
  102 unregister_sockfilter(struct NFDescriptor *nfp, struct protosw *pr, int flags)
  103 {       int s;
  104 
  105         s = splhigh();
  106         TAILQ_REMOVE(&nf_list, nfp, nf_list);
  107         /* Only globals are attached to the protosw entry */
  108         if (nfp->nf_flags & NFD_GLOBAL)
  109                 TAILQ_REMOVE(&pr->pr_sfilter, nfp, nf_next);
  110         splx(s);
  111         return(0);
  112 }
  113 
  114 struct NFDescriptor *
  115 find_nke(unsigned int handle)
  116 {       struct NFDescriptor *nfp;
  117 
  118         nfp = nf_list.tqh_first;
  119         while (nfp)
  120         {       if (nfp->nf_handle == handle)
  121                         return(nfp);
  122                 nfp = nfp->nf_list.tqe_next;
  123         }
  124         return(NULL);
  125 }
  126 
  127 /*
  128  * Insert a previously registered, non-global, NKE into the list of
  129  *  active NKEs for this socket.  Then invoke its "attach/create" entry.
  130  * Assumed called with protection in place (spl/mutex/whatever)
  131  * XXX: How to which extension is not found, on error.
  132  */
  133 int
  134 nke_insert(struct socket *so, struct so_nke *np)
  135 {       int s, error;
  136         struct kextcb *kp, *kp1;
  137         struct NFDescriptor *nf1, *nf2 = NULL;
  138 
  139         if (np->nke_where != NULL)
  140         {       if ((nf2 = find_nke(np->nke_where)) == NULL)
  141                 {       /* ??? */
  142                         return(ENXIO);/* XXX */
  143                 }
  144         }
  145 
  146         if ((nf1 = find_nke(np->nke_handle)) == NULL)
  147         {       /* ??? */
  148                 return(ENXIO);/* XXX */
  149         }
  150 
  151         kp = so->so_ext;
  152         kp1 = NULL;
  153         if (np->nke_flags & NFF_BEFORE)
  154         {       if (nf2)
  155                 {       while (kp)
  156                         {       if (kp->e_nfd == nf2)
  157                                         break;
  158                                 kp1 = kp;
  159                                 kp = kp->e_next;
  160                         }
  161                         if (kp == NULL)
  162                                 return(ENXIO);/* XXX */
  163                 }
  164         } else
  165         {       if (nf2)
  166                 {       while (kp)
  167                         {       if (kp->e_nfd == nf2)
  168                                         break;
  169                                 kp1 = kp;
  170                                 kp = kp->e_next;
  171                         }
  172                         if (kp == NULL)
  173                                 return(ENXIO);/* XXX */
  174                 }
  175                 kp1 = kp;
  176         }
  177         /*
  178          * Here with kp1 pointing to the insertion point.
  179          * If null, this is first entry.
  180          * Now, create and insert the descriptor.
  181          */
  182 
  183         MALLOC(kp, struct kextcb *, sizeof(*kp), M_TEMP, M_WAITOK);
  184         if (kp == NULL)
  185                 return(ENOBUFS); /* so_free will clean up */
  186         bzero(kp, sizeof (*kp));
  187         if (kp1 == NULL)
  188         {       kp->e_next = so->so_ext;
  189                 so->so_ext = kp;
  190         } else
  191         {       kp->e_next = kp1->e_next;
  192                 kp1->e_next = kp;
  193         }
  194         kp->e_fcb = NULL;
  195         kp->e_nfd = nf1;
  196         kp->e_soif = nf1->nf_soif;
  197         kp->e_sout = nf1->nf_soutil;
  198         /*
  199          * Ignore return value for create
  200          * Everyone gets a chance at startup
  201          */
  202         if (kp->e_soif && kp->e_soif->sf_socreate)
  203                 (*kp->e_soif->sf_socreate)(so, so->so_proto, kp);
  204         return(0);
  205 }
  206 
  207 /*
  208  * The following gunk is a fix for Symantec's broken NPC kext
  209  * Symantec's NPC kext does not check that the kextcb->e_fcb
  210  * is not NULL before derefing it. The result is a panic in
  211  * the very few cases where the e_fcb is actually NULL.
  212  *
  213  * This gross chunk of code copies the old function ptrs
  214  * supplied by the kext and wraps a few select ones in
  215  * our own functions that just check for NULL before
  216  * calling in to the kext.
  217  */
  218 
  219 static struct sockif*   g_symantec_if_funcs = NULL;
  220 static struct sockutil* g_symantec_util_funcs = NULL;
  221 static int sym_fix_sbflush(struct sockbuf *, struct kextcb *);
  222 static int sym_fix_sbappend(struct sockbuf *, struct mbuf *, struct kextcb *);
  223 static int sym_fix_soclose(struct socket *, struct kextcb *);
  224 static int sym_fix_sofree(struct socket *, struct kextcb *);
  225 static int sym_fix_soconnect(struct socket *, struct sockaddr *, struct kextcb *);
  226 static int sym_fix_soisconnected(struct socket *, struct kextcb *);
  227 static int sym_fix_sosend(struct socket *, struct sockaddr **, struct uio **, struct mbuf **,
  228                         struct mbuf **, int *, struct kextcb *);
  229 static int sym_fix_socantrcvmore(struct socket *, struct kextcb *);
  230 static int sym_fix_socontrol(struct socket *, struct sockopt *, struct kextcb *);
  231 
  232 static int sockfilter_fix_symantec_bug(struct NFDescriptor* theirDesc)
  233 {
  234         if (!g_symantec_if_funcs ) {
  235                 MALLOC(g_symantec_if_funcs, struct sockif*, sizeof(*g_symantec_if_funcs), M_TEMP, M_WAITOK);
  236                 
  237                 if (!g_symantec_if_funcs)
  238                         return ENOMEM;
  239                 
  240                 *g_symantec_if_funcs = *theirDesc->nf_soif;
  241         }
  242         
  243         if (!g_symantec_util_funcs) {
  244                 MALLOC(g_symantec_util_funcs, struct sockutil*, sizeof(*g_symantec_util_funcs), M_TEMP, M_WAITOK);
  245                 
  246                 if (!g_symantec_util_funcs)
  247                         return ENOMEM;
  248                 
  249                 *g_symantec_util_funcs = *theirDesc->nf_soutil;
  250         }
  251         
  252         if (theirDesc->nf_soutil->su_sbflush)
  253                 theirDesc->nf_soutil->su_sbflush = sym_fix_sbflush;
  254         if (theirDesc->nf_soutil->su_sbappend)
  255                 theirDesc->nf_soutil->su_sbappend = sym_fix_sbappend;
  256         if (theirDesc->nf_soif->sf_soclose)
  257                 theirDesc->nf_soif->sf_soclose = sym_fix_soclose;
  258         if (theirDesc->nf_soif->sf_sofree)
  259                 theirDesc->nf_soif->sf_sofree = sym_fix_sofree;
  260         if (theirDesc->nf_soif->sf_soconnect)
  261                 theirDesc->nf_soif->sf_soconnect = sym_fix_soconnect;
  262         if (theirDesc->nf_soif->sf_soisconnected)
  263                 theirDesc->nf_soif->sf_soisconnected = sym_fix_soisconnected;
  264         if (theirDesc->nf_soif->sf_sosend)
  265                 theirDesc->nf_soif->sf_sosend = sym_fix_sosend;
  266         if (theirDesc->nf_soif->sf_socantrcvmore)
  267                 theirDesc->nf_soif->sf_socantrcvmore = sym_fix_socantrcvmore;
  268         if (theirDesc->nf_soif->sf_socontrol)
  269                 theirDesc->nf_soif->sf_socontrol = sym_fix_socontrol;
  270         
  271         return 0;
  272 }
  273 
  274 static int sym_fix_sbflush(struct sockbuf *p1, struct kextcb *p2)
  275 {
  276         if (p2->e_fcb != NULL && g_symantec_util_funcs)
  277                 return g_symantec_util_funcs->su_sbflush(p1, p2);
  278         else
  279                 return 0;
  280 }
  281 
  282 static int sym_fix_sbappend(struct sockbuf *p1, struct mbuf *p2, struct kextcb *p3)
  283 {
  284         if (p3->e_fcb != NULL && g_symantec_util_funcs)
  285                 return g_symantec_util_funcs->su_sbappend(p1, p2, p3);
  286         else
  287                 return 0;
  288 }
  289 
  290 static int sym_fix_soclose(struct socket *p1, struct kextcb *p2)
  291 {
  292         if (p2->e_fcb != NULL && g_symantec_if_funcs)
  293                 return g_symantec_if_funcs->sf_soclose(p1, p2);
  294         else
  295                 return 0;
  296 }
  297 
  298 static int sym_fix_sofree(struct socket *p1, struct kextcb *p2)
  299 {
  300         if (p2->e_fcb != NULL && g_symantec_if_funcs)
  301                 return g_symantec_if_funcs->sf_sofree(p1, p2);
  302         else
  303                 return 0;
  304 }
  305 
  306 static int sym_fix_soconnect(struct socket *p1, struct sockaddr *p2, struct kextcb *p3)
  307 {
  308         if (p3->e_fcb != NULL && g_symantec_if_funcs)
  309                 return g_symantec_if_funcs->sf_soconnect(p1, p2, p3);
  310         else
  311                 return 0;
  312 }
  313 
  314 static int sym_fix_soisconnected(struct socket *p1, struct kextcb *p2)
  315 {
  316         if (p2->e_fcb != NULL && g_symantec_if_funcs)
  317                 return g_symantec_if_funcs->sf_soisconnected(p1, p2);
  318         else
  319                 return 0;
  320 }
  321 
  322 static int sym_fix_sosend(struct socket *p1, struct sockaddr **p2, struct uio **p3, struct mbuf **p4,
  323                         struct mbuf **p5, int *p6, struct kextcb *p7)
  324 {
  325         if (p7->e_fcb != NULL && g_symantec_if_funcs)
  326                 return g_symantec_if_funcs->sf_sosend(p1, p2, p3, p4, p5, p6, p7);
  327         else
  328                 return 0;
  329 }
  330 
  331 static int sym_fix_socantrcvmore(struct socket *p1, struct kextcb *p2)
  332 {
  333         if (p2->e_fcb != NULL && g_symantec_if_funcs)
  334                 return g_symantec_if_funcs->sf_socantrcvmore(p1, p2);
  335         else
  336                 return 0;
  337 }
  338 
  339 static int sym_fix_socontrol(struct socket *p1, struct sockopt *p2, struct kextcb *p3)
  340 {
  341         if (p3->e_fcb != NULL && g_symantec_if_funcs)
  342                 return g_symantec_if_funcs->sf_socontrol(p1, p2, p3);
  343         else
  344                 return 0;
  345 }

Cache object: 74ebb86a0fb8b63bf7894f055bd5d4e7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.