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/netpfil/ipfilter/netinet/ip_pptp_pxy.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) 2012 by Darren Reed.
    3  *
    4  * Simple PPTP transparent proxy for in-kernel use.  For use with the NAT
    5  * code.
    6  *
    7  * $Id$
    8  *
    9  */
   10 #define IPF_PPTP_PROXY
   11 
   12 
   13 
   14 /*
   15  * PPTP proxy
   16  */
   17 typedef struct pptp_side {
   18         u_32_t          pptps_nexthdr;
   19         u_32_t          pptps_next;
   20         int             pptps_state;
   21         int             pptps_gothdr;
   22         int             pptps_len;
   23         int             pptps_bytes;
   24         char            *pptps_wptr;
   25         char            pptps_buffer[512];
   26 } pptp_side_t;
   27 
   28 typedef struct pptp_pxy {
   29         nat_t           *pptp_nat;
   30         struct ipstate  *pptp_state;
   31         u_short         pptp_call[2];
   32         pptp_side_t     pptp_side[2];
   33         ipnat_t         *pptp_rule;
   34 } pptp_pxy_t;
   35 
   36 typedef struct pptp_hdr {
   37         u_short         pptph_len;
   38         u_short         pptph_type;
   39         u_32_t          pptph_cookie;
   40 } pptp_hdr_t;
   41 
   42 #define PPTP_MSGTYPE_CTL        1
   43 #define PPTP_MTCTL_STARTREQ     1
   44 #define PPTP_MTCTL_STARTREP     2
   45 #define PPTP_MTCTL_STOPREQ      3
   46 #define PPTP_MTCTL_STOPREP      4
   47 #define PPTP_MTCTL_ECHOREQ      5
   48 #define PPTP_MTCTL_ECHOREP      6
   49 #define PPTP_MTCTL_OUTREQ       7
   50 #define PPTP_MTCTL_OUTREP       8
   51 #define PPTP_MTCTL_INREQ        9
   52 #define PPTP_MTCTL_INREP        10
   53 #define PPTP_MTCTL_INCONNECT    11
   54 #define PPTP_MTCTL_CLEAR        12
   55 #define PPTP_MTCTL_DISCONNECT   13
   56 #define PPTP_MTCTL_WANERROR     14
   57 #define PPTP_MTCTL_LINKINFO     15
   58 
   59 
   60 void ipf_p_pptp_main_load(void);
   61 void ipf_p_pptp_main_unload(void);
   62 int ipf_p_pptp_new(void *, fr_info_t *, ap_session_t *, nat_t *);
   63 void ipf_p_pptp_del(ipf_main_softc_t *, ap_session_t *);
   64 int ipf_p_pptp_inout(void *, fr_info_t *, ap_session_t *, nat_t *);
   65 void ipf_p_pptp_donatstate(fr_info_t *, nat_t *, pptp_pxy_t *);
   66 int ipf_p_pptp_message(fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *);
   67 int ipf_p_pptp_nextmessage(fr_info_t *, nat_t *, pptp_pxy_t *, int);
   68 int ipf_p_pptp_mctl(fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *);
   69 
   70 static  frentry_t       pptpfr;
   71 
   72 static  int     pptp_proxy_init = 0;
   73 static  int     ipf_p_pptp_debug = 0;
   74 static  int     ipf_p_pptp_gretimeout = IPF_TTLVAL(120);        /* 2 minutes */
   75 
   76 
   77 /*
   78  * PPTP application proxy initialization.
   79  */
   80 void
   81 ipf_p_pptp_main_load(void)
   82 {
   83         bzero((char *)&pptpfr, sizeof(pptpfr));
   84         pptpfr.fr_ref = 1;
   85         pptpfr.fr_age[0] = ipf_p_pptp_gretimeout;
   86         pptpfr.fr_age[1] = ipf_p_pptp_gretimeout;
   87         pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
   88         MUTEX_INIT(&pptpfr.fr_lock, "PPTP proxy rule lock");
   89         pptp_proxy_init = 1;
   90 }
   91 
   92 
   93 void
   94 ipf_p_pptp_main_unload(void)
   95 {
   96         if (pptp_proxy_init == 1) {
   97                 MUTEX_DESTROY(&pptpfr.fr_lock);
   98                 pptp_proxy_init = 0;
   99         }
  100 }
  101 
  102 
  103 /*
  104  * Setup for a new PPTP proxy.
  105  *
  106  * NOTE: The printf's are broken up with %s in them to prevent them being
  107  * optimised into puts statements on FreeBSD (this doesn't exist in the kernel)
  108  */
  109 int
  110 ipf_p_pptp_new(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat)
  111 {
  112         pptp_pxy_t *pptp;
  113         ipnat_t *ipn;
  114         ipnat_t *np;
  115         int size;
  116         ip_t *ip;
  117 
  118         if (fin->fin_v != 4)
  119                 return (-1);
  120 
  121         ip = fin->fin_ip;
  122         np = nat->nat_ptr;
  123         size = np->in_size;
  124 
  125         if (ipf_nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_osrcip,
  126                           ip->ip_dst) != NULL) {
  127                 if (ipf_p_pptp_debug > 0)
  128                         printf("ipf_p_pptp_new: GRE session already exists\n");
  129                 return (-1);
  130         }
  131 
  132         KMALLOC(pptp, pptp_pxy_t *);
  133         if (pptp == NULL) {
  134                 if (ipf_p_pptp_debug > 0)
  135                         printf("ipf_p_pptp_new: malloc for aps_data failed\n");
  136                 return (-1);
  137         }
  138         KMALLOCS(ipn, ipnat_t *, size);
  139         if (ipn == NULL) {
  140                 KFREE(pptp);
  141                 return (-1);
  142         }
  143 
  144         aps->aps_data = pptp;
  145         aps->aps_psiz = sizeof(*pptp);
  146         bzero((char *)pptp, sizeof(*pptp));
  147         bzero((char *)ipn, size);
  148         pptp->pptp_rule = ipn;
  149 
  150         /*
  151          * Create NAT rule against which the tunnel/transport mapping is
  152          * created.  This is required because the current NAT rule does not
  153          * describe GRE but TCP instead.
  154          */
  155         ipn->in_size = size;
  156         ipn->in_ifps[0] = fin->fin_ifp;
  157         ipn->in_apr = NULL;
  158         ipn->in_use = 1;
  159         ipn->in_hits = 1;
  160         ipn->in_ippip = 1;
  161         ipn->in_snip = ntohl(nat->nat_nsrcaddr);
  162         ipn->in_nsrcaddr = fin->fin_saddr;
  163         ipn->in_dnip = ntohl(nat->nat_ndstaddr);
  164         ipn->in_ndstaddr = nat->nat_ndstaddr;
  165         ipn->in_redir = np->in_redir;
  166         ipn->in_osrcaddr = nat->nat_osrcaddr;
  167         ipn->in_odstaddr = nat->nat_odstaddr;
  168         ipn->in_osrcmsk = 0xffffffff;
  169         ipn->in_nsrcmsk = 0xffffffff;
  170         ipn->in_odstmsk = 0xffffffff;
  171         ipn->in_ndstmsk = 0xffffffff;
  172         ipn->in_flags = (np->in_flags | IPN_PROXYRULE);
  173         MUTEX_INIT(&ipn->in_lock, "pptp proxy NAT rule");
  174 
  175         ipn->in_namelen = np->in_namelen;
  176         bcopy(np->in_names, ipn->in_ifnames, ipn->in_namelen);
  177         ipn->in_ifnames[0] = np->in_ifnames[0];
  178         ipn->in_ifnames[1] = np->in_ifnames[1];
  179 
  180         ipn->in_pr[0] = IPPROTO_GRE;
  181         ipn->in_pr[1] = IPPROTO_GRE;
  182 
  183         pptp->pptp_side[0].pptps_wptr = pptp->pptp_side[0].pptps_buffer;
  184         pptp->pptp_side[1].pptps_wptr = pptp->pptp_side[1].pptps_buffer;
  185         return (0);
  186 }
  187 
  188 
  189 void
  190 ipf_p_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp)
  191 {
  192         ipf_main_softc_t *softc = fin->fin_main_soft;
  193         fr_info_t fi;
  194         grehdr_t gre;
  195         nat_t *nat2;
  196         u_char p;
  197         ip_t *ip;
  198 
  199         ip = fin->fin_ip;
  200         p = ip->ip_p;
  201 
  202         nat2 = pptp->pptp_nat;
  203         if ((nat2 == NULL) || (pptp->pptp_state == NULL)) {
  204                 bcopy((char *)fin, (char *)&fi, sizeof(fi));
  205                 bzero((char *)&gre, sizeof(gre));
  206                 fi.fin_fi.fi_p = IPPROTO_GRE;
  207                 fi.fin_fr = &pptpfr;
  208                 if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) ||
  209                     (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) {
  210                         fi.fin_data[0] = pptp->pptp_call[0];
  211                         fi.fin_data[1] = pptp->pptp_call[1];
  212                 } else {
  213                         fi.fin_data[0] = pptp->pptp_call[1];
  214                         fi.fin_data[1] = pptp->pptp_call[0];
  215                 }
  216                 ip = fin->fin_ip;
  217                 ip->ip_p = IPPROTO_GRE;
  218                 fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG);
  219                 fi.fin_flx |= FI_IGNORE;
  220                 fi.fin_dp = &gre;
  221                 gre.gr_flags = htons(1 << 13);
  222 
  223                 fi.fin_fi.fi_saddr = nat->nat_osrcaddr;
  224                 fi.fin_fi.fi_daddr = nat->nat_odstaddr;
  225         }
  226 
  227         /*
  228          * Update NAT timeout/create NAT if missing.
  229          */
  230         if (nat2 != NULL)
  231                 ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe);
  232         else {
  233 #ifdef USE_MUTEXES
  234                 ipf_nat_softc_t *softn = softc->ipf_nat_soft;
  235 #endif
  236 
  237                 MUTEX_ENTER(&softn->ipf_nat_new);
  238                 nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat,
  239                                    NAT_SLAVE, nat->nat_dir);
  240                 MUTEX_EXIT(&softn->ipf_nat_new);
  241                 if (nat2 != NULL) {
  242                         (void) ipf_nat_proto(&fi, nat2, 0);
  243                         MUTEX_ENTER(&nat2->nat_lock);
  244                         ipf_nat_update(&fi, nat2);
  245                         MUTEX_EXIT(&nat2->nat_lock);
  246                 }
  247         }
  248 
  249         READ_ENTER(&softc->ipf_state);
  250         if (pptp->pptp_state != NULL) {
  251                 ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti);
  252                 RWLOCK_EXIT(&softc->ipf_state);
  253         } else {
  254                 RWLOCK_EXIT(&softc->ipf_state);
  255                 if (nat2 != NULL) {
  256                         if (nat->nat_dir == NAT_INBOUND)
  257                                 fi.fin_fi.fi_daddr = nat2->nat_ndstaddr;
  258                         else
  259                                 fi.fin_fi.fi_saddr = nat2->nat_osrcaddr;
  260                 }
  261                 fi.fin_ifp = NULL;
  262                 (void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0);
  263         }
  264         ip->ip_p = p;
  265         return;
  266 }
  267 
  268 
  269 /*
  270  * Try and build up the next PPTP message in the TCP stream and if we can
  271  * build it up completely (fits in our buffer) then pass it off to the message
  272  * parsing function.
  273  */
  274 int
  275 ipf_p_pptp_nextmessage(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp, int rev)
  276 {
  277         static const char *funcname = "ipf_p_pptp_nextmessage";
  278         pptp_side_t *pptps;
  279         u_32_t start, end;
  280         pptp_hdr_t *hdr;
  281         tcphdr_t *tcp;
  282         int dlen, off;
  283         u_short len;
  284         char *msg;
  285 
  286         tcp = fin->fin_dp;
  287         dlen = fin->fin_dlen - (TCP_OFF(tcp) << 2);
  288         start = ntohl(tcp->th_seq);
  289         pptps = &pptp->pptp_side[rev];
  290         off = (char *)tcp - (char *)fin->fin_ip + (TCP_OFF(tcp) << 2) +
  291               fin->fin_ipoff;
  292 
  293         if (dlen <= 0)
  294                 return (0);
  295         /*
  296          * If the complete data packet is before what we expect to see
  297          * "next", just ignore it as the chances are we've already seen it.
  298          * The next if statement following this one really just causes packets
  299          * ahead of what we've seen to be dropped, implying that something in
  300          * the middle went missing and we want to see that first.
  301          */
  302         end = start + dlen;
  303         if (pptps->pptps_next > end && pptps->pptps_next > start)
  304                 return (0);
  305 
  306         if (pptps->pptps_next != start) {
  307                 if (ipf_p_pptp_debug > 5)
  308                         printf("%s: next (%x) != start (%x)\n", funcname,
  309                                 pptps->pptps_next, start);
  310                 return (-1);
  311         }
  312 
  313         msg = (char *)fin->fin_dp + (TCP_OFF(tcp) << 2);
  314 
  315         while (dlen > 0) {
  316                 off += pptps->pptps_bytes;
  317                 if (pptps->pptps_gothdr == 0) {
  318                         /*
  319                          * PPTP has an 8 byte header that inclues the cookie.
  320                          * The start of every message should include one and
  321                          * it should match 1a2b3c4d.  Byte order is ignored,
  322                          * deliberately, when printing out the error.
  323                          */
  324                         len = MIN(8 - pptps->pptps_bytes, dlen);
  325                         COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
  326                         pptps->pptps_bytes += len;
  327                         pptps->pptps_wptr += len;
  328                         hdr = (pptp_hdr_t *)pptps->pptps_buffer;
  329                         if (pptps->pptps_bytes == 8) {
  330                                 pptps->pptps_next += 8;
  331                                 if (ntohl(hdr->pptph_cookie) != 0x1a2b3c4d) {
  332                                         if (ipf_p_pptp_debug > 1)
  333                                                 printf("%s: bad cookie (%x)\n",
  334                                                        funcname,
  335                                                        hdr->pptph_cookie);
  336                                         return (-1);
  337                                 }
  338                         }
  339                         dlen -= len;
  340                         msg += len;
  341                         off += len;
  342 
  343                         pptps->pptps_gothdr = 1;
  344                         len = ntohs(hdr->pptph_len);
  345                         pptps->pptps_len = len;
  346                         pptps->pptps_nexthdr += len;
  347 
  348                         /*
  349                          * If a message is too big for the buffer, just set
  350                          * the fields for the next message to come along.
  351                          * The messages defined in RFC 2637 will not exceed
  352                          * 512 bytes (in total length) so this is likely a
  353                          * bad data packet, anyway.
  354                          */
  355                         if (len > sizeof(pptps->pptps_buffer)) {
  356                                 if (ipf_p_pptp_debug > 3)
  357                                         printf("%s: message too big (%d)\n",
  358                                                funcname, len);
  359                                 pptps->pptps_next = pptps->pptps_nexthdr;
  360                                 pptps->pptps_wptr = pptps->pptps_buffer;
  361                                 pptps->pptps_gothdr = 0;
  362                                 pptps->pptps_bytes = 0;
  363                                 pptps->pptps_len = 0;
  364                                 break;
  365                         }
  366                 }
  367 
  368                 len = MIN(pptps->pptps_len - pptps->pptps_bytes, dlen);
  369                 COPYDATA(fin->fin_m, off, len, pptps->pptps_wptr);
  370                 pptps->pptps_bytes += len;
  371                 pptps->pptps_wptr += len;
  372                 pptps->pptps_next += len;
  373 
  374                 if (pptps->pptps_len > pptps->pptps_bytes)
  375                         break;
  376 
  377                 ipf_p_pptp_message(fin, nat, pptp, pptps);
  378                 pptps->pptps_wptr = pptps->pptps_buffer;
  379                 pptps->pptps_gothdr = 0;
  380                 pptps->pptps_bytes = 0;
  381                 pptps->pptps_len = 0;
  382 
  383                 start += len;
  384                 msg += len;
  385                 dlen -= len;
  386         }
  387 
  388         return (0);
  389 }
  390 
  391 
  392 /*
  393  * handle a complete PPTP message
  394  */
  395 int
  396 ipf_p_pptp_message(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp,
  397         pptp_side_t *pptps)
  398 {
  399         pptp_hdr_t *hdr = (pptp_hdr_t *)pptps->pptps_buffer;
  400 
  401         switch (ntohs(hdr->pptph_type))
  402         {
  403         case PPTP_MSGTYPE_CTL :
  404                 ipf_p_pptp_mctl(fin, nat, pptp, pptps);
  405                 break;
  406 
  407         default :
  408                 break;
  409         }
  410         return (0);
  411 }
  412 
  413 
  414 /*
  415  * handle a complete PPTP control message
  416  */
  417 int
  418 ipf_p_pptp_mctl(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp,
  419         pptp_side_t *pptps)
  420 {
  421         u_short *buffer = (u_short *)(pptps->pptps_buffer);
  422         pptp_side_t *pptpo;
  423 
  424         if (pptps == &pptp->pptp_side[0])
  425                 pptpo = &pptp->pptp_side[1];
  426         else
  427                 pptpo = &pptp->pptp_side[0];
  428 
  429         /*
  430          * Breakout to handle all the various messages.  Most are just state
  431          * transition.
  432          */
  433         switch (ntohs(buffer[4]))
  434         {
  435         case PPTP_MTCTL_STARTREQ :
  436                 pptps->pptps_state = PPTP_MTCTL_STARTREQ;
  437                 break;
  438         case PPTP_MTCTL_STARTREP :
  439                 if (pptpo->pptps_state == PPTP_MTCTL_STARTREQ)
  440                         pptps->pptps_state = PPTP_MTCTL_STARTREP;
  441                 break;
  442         case PPTP_MTCTL_STOPREQ :
  443                 pptps->pptps_state = PPTP_MTCTL_STOPREQ;
  444                 break;
  445         case PPTP_MTCTL_STOPREP :
  446                 if (pptpo->pptps_state == PPTP_MTCTL_STOPREQ)
  447                         pptps->pptps_state = PPTP_MTCTL_STOPREP;
  448                 break;
  449         case PPTP_MTCTL_ECHOREQ :
  450                 pptps->pptps_state = PPTP_MTCTL_ECHOREQ;
  451                 break;
  452         case PPTP_MTCTL_ECHOREP :
  453                 if (pptpo->pptps_state == PPTP_MTCTL_ECHOREQ)
  454                         pptps->pptps_state = PPTP_MTCTL_ECHOREP;
  455                 break;
  456         case PPTP_MTCTL_OUTREQ :
  457                 pptps->pptps_state = PPTP_MTCTL_OUTREQ;
  458                 break;
  459         case PPTP_MTCTL_OUTREP :
  460                 if (pptpo->pptps_state == PPTP_MTCTL_OUTREQ) {
  461                         pptps->pptps_state = PPTP_MTCTL_OUTREP;
  462                         pptp->pptp_call[0] = buffer[7];
  463                         pptp->pptp_call[1] = buffer[6];
  464                         ipf_p_pptp_donatstate(fin, nat, pptp);
  465                 }
  466                 break;
  467         case PPTP_MTCTL_INREQ :
  468                 pptps->pptps_state = PPTP_MTCTL_INREQ;
  469                 break;
  470         case PPTP_MTCTL_INREP :
  471                 if (pptpo->pptps_state == PPTP_MTCTL_INREQ) {
  472                         pptps->pptps_state = PPTP_MTCTL_INREP;
  473                         pptp->pptp_call[0] = buffer[7];
  474                         pptp->pptp_call[1] = buffer[6];
  475                         ipf_p_pptp_donatstate(fin, nat, pptp);
  476                 }
  477                 break;
  478         case PPTP_MTCTL_INCONNECT :
  479                 pptps->pptps_state = PPTP_MTCTL_INCONNECT;
  480                 break;
  481         case PPTP_MTCTL_CLEAR :
  482                 pptps->pptps_state = PPTP_MTCTL_CLEAR;
  483                 break;
  484         case PPTP_MTCTL_DISCONNECT :
  485                 pptps->pptps_state = PPTP_MTCTL_DISCONNECT;
  486                 break;
  487         case PPTP_MTCTL_WANERROR :
  488                 pptps->pptps_state = PPTP_MTCTL_WANERROR;
  489                 break;
  490         case PPTP_MTCTL_LINKINFO :
  491                 pptps->pptps_state = PPTP_MTCTL_LINKINFO;
  492                 break;
  493         }
  494 
  495         return (0);
  496 }
  497 
  498 
  499 /*
  500  * For outgoing PPTP packets.  refresh timeouts for NAT & state entries, if
  501  * we can.  If they have disappeared, recreate them.
  502  */
  503 int
  504 ipf_p_pptp_inout(void *arg, fr_info_t *fin, ap_session_t *aps, nat_t *nat)
  505 {
  506         pptp_pxy_t *pptp;
  507         tcphdr_t *tcp;
  508         int rev;
  509 
  510         if ((fin->fin_out == 1) && (nat->nat_dir == NAT_INBOUND))
  511                 rev = 1;
  512         else if ((fin->fin_out == 0) && (nat->nat_dir == NAT_OUTBOUND))
  513                 rev = 1;
  514         else
  515                 rev = 0;
  516 
  517         tcp = (tcphdr_t *)fin->fin_dp;
  518         if ((tcp->th_flags & TH_OPENING) == TH_OPENING) {
  519                 pptp = (pptp_pxy_t *)aps->aps_data;
  520                 pptp->pptp_side[1 - rev].pptps_next = ntohl(tcp->th_ack);
  521                 pptp->pptp_side[1 - rev].pptps_nexthdr = ntohl(tcp->th_ack);
  522                 pptp->pptp_side[rev].pptps_next = ntohl(tcp->th_seq) + 1;
  523                 pptp->pptp_side[rev].pptps_nexthdr = ntohl(tcp->th_seq) + 1;
  524         }
  525         return (ipf_p_pptp_nextmessage(fin, nat, (pptp_pxy_t *)aps->aps_data,
  526                                      rev));
  527 }
  528 
  529 
  530 /*
  531  * clean up after ourselves.
  532  */
  533 void
  534 ipf_p_pptp_del(ipf_main_softc_t *softc, ap_session_t *aps)
  535 {
  536         pptp_pxy_t *pptp;
  537 
  538         pptp = aps->aps_data;
  539 
  540         if (pptp != NULL) {
  541                 /*
  542                  * Don't bother changing any of the NAT structure details,
  543                  * *_del() is on a callback from aps_free(), from nat_delete()
  544                  */
  545 
  546                 READ_ENTER(&softc->ipf_state);
  547                 if (pptp->pptp_state != NULL) {
  548                         ipf_state_setpending(softc, pptp->pptp_state);
  549                 }
  550                 RWLOCK_EXIT(&softc->ipf_state);
  551 
  552                 if (pptp->pptp_nat != NULL)
  553                         ipf_nat_setpending(softc, pptp->pptp_nat);
  554                 pptp->pptp_rule->in_flags |= IPN_DELETE;
  555                 ipf_nat_rule_deref(softc, &pptp->pptp_rule);
  556         }
  557 }

Cache object: 26332e1e99a34af30cd3d8711bc1db97


[ 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.