1507                 * timer on it as we'll never see an error if it fails to
1508                 * connect.
1509                 */
1510                 (void) fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1511                                   is->is_flags);
1512                 MUTEX_EXIT(&is->is_lock);
1513 #ifdef  IPFILTER_SCAN
1514                 if ((is->is_flags & SI_CLONE) == 0)
1515                         (void) ipsc_attachis(is);
1516 #endif
1517         } else {
1518                 MUTEX_EXIT(&is->is_lock);
1519         }
1520 #ifdef  IPFILTER_SYNC
1521         if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
1522                 is->is_sync = ipfsync_new(SMC_STATE, fin, is);
1523 #endif
1524         if (ifs->ifs_ipstate_logging)
1525                 ipstate_log(is, ISL_NEW, ifs);
1526 
1527         RWLOCK_EXIT(&ifs->ifs_ipf_state);
1528         fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr);
1529         fin->fin_flx |= FI_STATE;
1530         if (fin->fin_flx & FI_FRAG)
1531                 (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
1532 
1533         return is;
1534 }
1535 
1536 
1537 /* ------------------------------------------------------------------------ */
1538 /* Function:    fr_tcpoptions                                               */
1539 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1540 /* Parameters:  fin(I) - pointer to packet information                      */
1541 /*              tcp(I) - pointer to TCP packet header                       */
1542 /*              td(I)  - pointer to TCP data held as part of the state      */
1543 /*                                                                          */
1544 /* Look after the TCP header for any options and deal with those that are   */
1545 /* present.  Record details about those that we recogise.                   */
1546 /* ------------------------------------------------------------------------ */
 
2297                                 is->is_sport = sp;
2298                                 is->is_send = ntohl(tcp->th_seq);
2299                         } else {
2300                                 is->is_sport = dp;
2301                                 is->is_send = ntohl(tcp->th_ack);
2302                         }
2303                         is->is_maxsend = is->is_send + 1;
2304                 } else if ((flags & SI_W_DPORT) != 0) {
2305                         if (rev == 0) {
2306                                 is->is_dport = dp;
2307                                 is->is_dend = ntohl(tcp->th_ack);
2308                         } else {
2309                                 is->is_dport = sp;
2310                                 is->is_dend = ntohl(tcp->th_seq);
2311                         }
2312                         is->is_maxdend = is->is_dend + 1;
2313                 }
2314                 is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT);
2315                 if ((flags & SI_CLONED) && ifs->ifs_ipstate_logging)
2316                         ipstate_log(is, ISL_CLONE, ifs);
2317         }
2318 
2319         ret = -1;
2320 
2321         if (is->is_flx[out][rev] == 0) {
2322                 is->is_flx[out][rev] = flx;
2323                 /*
2324                  * If we are dealing with the first packet coming in reverse
2325                  * direction (sent by peer), then we have to set options into
2326                  * state.
2327                  */
2328                 if (rev == 1 && is->is_optmsk[1] == 0x0) {
2329                         is->is_optmsk[1] = 0xffffffff;
2330                         is->is_opt[1] = fin->fin_optmsk;
2331                         DTRACE_PROBE(set_rev_opts);
2332                 }
2333                 if (is->is_v == 6) {
2334                         is->is_opt[rev] &= ~0x8;
2335                         is->is_optmsk[rev] &= ~0x8;
2336                 }
 
3380                 ipfsync_del(is->is_sync);
3381 #endif
3382 #ifdef  IPFILTER_SCAN
3383         (void) ipsc_detachis(is);
3384 #endif
3385 
3386         /*
3387          * Now remove it from master list of state table entries.
3388          */
3389         if (is->is_pnext != NULL) {
3390                 *is->is_pnext = is->is_next;
3391                 if (is->is_next != NULL) {
3392                         is->is_next->is_pnext = is->is_pnext;
3393                         is->is_next = NULL;
3394                 }
3395                 is->is_pnext = NULL;
3396         }
3397  
3398         if (ifs->ifs_ipstate_logging != 0 && why != 0)
3399                 ipstate_log(is, why, ifs);
3400 
3401         if (is->is_rule != NULL) {
3402                 is->is_rule->fr_statecnt--;
3403                 (void)fr_derefrule(&is->is_rule, ifs);
3404         }
3405 
3406         MUTEX_DESTROY(&is->is_lock);
3407         KFREE(is);
3408         ifs->ifs_ips_num--;
3409 
3410         return (0);
3411 }
3412 
3413 
3414 /* ------------------------------------------------------------------------ */
3415 /* Function:    fr_timeoutstate                                             */
3416 /* Returns:     Nil                                                         */
3417 /* Parameters:  ifs - ipf stack instance                                    */
3418 /*                                                                          */
3419 /* Slowly expire held state for thingslike UDP and ICMP.  The algorithm     */
3420 /* used here is to keep the queue sorted with the oldest things at the top  */
 
3914         if (rval == 2) {
3915                 DTRACE_PROBE1(state_keeping_timer, int, nstate);
3916                 rval = 1;
3917         }
3918         else if (rval == 1) {
3919                 tqe->tqe_state[dir] = nstate;
3920                 /*
3921                  * The nstate can either advance to a new state, or remain
3922                  * unchanged, resetting the timer by moving to the bottom of
3923                  * the queue.
3924                  */
3925                 DTRACE_PROBE1(state_done, int, nstate);
3926 
3927                 if ((tqe->tqe_flags & TQE_RULEBASED) == 0)
3928                         fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate, ifs);
3929         }
3930 
3931         return rval;
3932 }
3933 
3934 
3935 /* ------------------------------------------------------------------------ */
3936 /* Function:    ipstate_log                                                 */
3937 /* Returns:     Nil                                                         */
3938 /* Parameters:  is(I)   - pointer to state structure                        */
3939 /*              type(I) - type of log entry to create                       */
3940 /*                                                                          */
3941 /* Creates a state table log entry using the state structure and type info. */
3942 /* passed in.  Log packet/byte counts, source/destination address and other */
3943 /* protocol specific information.                                           */
3944 /* ------------------------------------------------------------------------ */
3945 void ipstate_log(is, type, ifs)
3946 struct ipstate *is;
3947 u_int type;
3948 ipf_stack_t *ifs;
3949 {
3950 #ifdef  IPFILTER_LOG
3951         struct  ipslog  ipsl;
3952         size_t sizes[1];
3953         void *items[1];
3954         int types[1];
 
 | 
 
 
1507                 * timer on it as we'll never see an error if it fails to
1508                 * connect.
1509                 */
1510                 (void) fr_tcp_age(&is->is_sti, fin, ifs->ifs_ips_tqtqb,
1511                                   is->is_flags);
1512                 MUTEX_EXIT(&is->is_lock);
1513 #ifdef  IPFILTER_SCAN
1514                 if ((is->is_flags & SI_CLONE) == 0)
1515                         (void) ipsc_attachis(is);
1516 #endif
1517         } else {
1518                 MUTEX_EXIT(&is->is_lock);
1519         }
1520 #ifdef  IPFILTER_SYNC
1521         if ((is->is_flags & IS_STATESYNC) && ((is->is_flags & SI_CLONE) == 0))
1522                 is->is_sync = ipfsync_new(SMC_STATE, fin, is);
1523 #endif
1524         if (ifs->ifs_ipstate_logging)
1525                 ipstate_log(is, ISL_NEW, ifs);
1526 
1527         if (IFS_CFWLOG(ifs))
1528                 ipf_log_cfwlog(is, ISL_NEW, ifs);
1529 
1530         RWLOCK_EXIT(&ifs->ifs_ipf_state);
1531         fin->fin_rev = IP6_NEQ(&is->is_dst, &fin->fin_daddr);
1532         fin->fin_flx |= FI_STATE;
1533         if (fin->fin_flx & FI_FRAG)
1534                 (void) fr_newfrag(fin, pass ^ FR_KEEPSTATE);
1535 
1536         return is;
1537 }
1538 
1539 
1540 /* ------------------------------------------------------------------------ */
1541 /* Function:    fr_tcpoptions                                               */
1542 /* Returns:     int - 1 == packet matches state entry, 0 == it does not     */
1543 /* Parameters:  fin(I) - pointer to packet information                      */
1544 /*              tcp(I) - pointer to TCP packet header                       */
1545 /*              td(I)  - pointer to TCP data held as part of the state      */
1546 /*                                                                          */
1547 /* Look after the TCP header for any options and deal with those that are   */
1548 /* present.  Record details about those that we recogise.                   */
1549 /* ------------------------------------------------------------------------ */
 
2300                                 is->is_sport = sp;
2301                                 is->is_send = ntohl(tcp->th_seq);
2302                         } else {
2303                                 is->is_sport = dp;
2304                                 is->is_send = ntohl(tcp->th_ack);
2305                         }
2306                         is->is_maxsend = is->is_send + 1;
2307                 } else if ((flags & SI_W_DPORT) != 0) {
2308                         if (rev == 0) {
2309                                 is->is_dport = dp;
2310                                 is->is_dend = ntohl(tcp->th_ack);
2311                         } else {
2312                                 is->is_dport = sp;
2313                                 is->is_dend = ntohl(tcp->th_seq);
2314                         }
2315                         is->is_maxdend = is->is_dend + 1;
2316                 }
2317                 is->is_flags &= ~(SI_W_SPORT|SI_W_DPORT);
2318                 if ((flags & SI_CLONED) && ifs->ifs_ipstate_logging)
2319                         ipstate_log(is, ISL_CLONE, ifs);
2320                 if ((flags & SI_CLONED) && IFS_CFWLOG(ifs))
2321                         ipf_log_cfwlog(is, ISL_CLONE, ifs);
2322         }
2323 
2324         ret = -1;
2325 
2326         if (is->is_flx[out][rev] == 0) {
2327                 is->is_flx[out][rev] = flx;
2328                 /*
2329                  * If we are dealing with the first packet coming in reverse
2330                  * direction (sent by peer), then we have to set options into
2331                  * state.
2332                  */
2333                 if (rev == 1 && is->is_optmsk[1] == 0x0) {
2334                         is->is_optmsk[1] = 0xffffffff;
2335                         is->is_opt[1] = fin->fin_optmsk;
2336                         DTRACE_PROBE(set_rev_opts);
2337                 }
2338                 if (is->is_v == 6) {
2339                         is->is_opt[rev] &= ~0x8;
2340                         is->is_optmsk[rev] &= ~0x8;
2341                 }
 
3385                 ipfsync_del(is->is_sync);
3386 #endif
3387 #ifdef  IPFILTER_SCAN
3388         (void) ipsc_detachis(is);
3389 #endif
3390 
3391         /*
3392          * Now remove it from master list of state table entries.
3393          */
3394         if (is->is_pnext != NULL) {
3395                 *is->is_pnext = is->is_next;
3396                 if (is->is_next != NULL) {
3397                         is->is_next->is_pnext = is->is_pnext;
3398                         is->is_next = NULL;
3399                 }
3400                 is->is_pnext = NULL;
3401         }
3402  
3403         if (ifs->ifs_ipstate_logging != 0 && why != 0)
3404                 ipstate_log(is, why, ifs);
3405 #if 0
3406         /*
3407          * For now, ipf_log_cfwlog() copes with all "why" values.
3408          * strictly speaking, though, they all map to one event, which for
3409          * now is not supported.
3410          */
3411         if (why != 0 && IFS_CFWLOG(ifs))
3412                 ipf_log_cfwlog(is, why, ifs);
3413 #endif
3414         if (is->is_rule != NULL) {
3415                 is->is_rule->fr_statecnt--;
3416                 (void)fr_derefrule(&is->is_rule, ifs);
3417         }
3418 
3419         MUTEX_DESTROY(&is->is_lock);
3420         KFREE(is);
3421         ifs->ifs_ips_num--;
3422 
3423         return (0);
3424 }
3425 
3426 
3427 /* ------------------------------------------------------------------------ */
3428 /* Function:    fr_timeoutstate                                             */
3429 /* Returns:     Nil                                                         */
3430 /* Parameters:  ifs - ipf stack instance                                    */
3431 /*                                                                          */
3432 /* Slowly expire held state for thingslike UDP and ICMP.  The algorithm     */
3433 /* used here is to keep the queue sorted with the oldest things at the top  */
 
3927         if (rval == 2) {
3928                 DTRACE_PROBE1(state_keeping_timer, int, nstate);
3929                 rval = 1;
3930         }
3931         else if (rval == 1) {
3932                 tqe->tqe_state[dir] = nstate;
3933                 /*
3934                  * The nstate can either advance to a new state, or remain
3935                  * unchanged, resetting the timer by moving to the bottom of
3936                  * the queue.
3937                  */
3938                 DTRACE_PROBE1(state_done, int, nstate);
3939 
3940                 if ((tqe->tqe_flags & TQE_RULEBASED) == 0)
3941                         fr_movequeue(tqe, tqe->tqe_ifq, tqtab + nstate, ifs);
3942         }
3943 
3944         return rval;
3945 }
3946 
3947 /* ------------------------------------------------------------------------ */
3948 /* Function:    ipstate_log                                                 */
3949 /* Returns:     Nil                                                         */
3950 /* Parameters:  is(I)   - pointer to state structure                        */
3951 /*              type(I) - type of log entry to create                       */
3952 /*                                                                          */
3953 /* Creates a state table log entry using the state structure and type info. */
3954 /* passed in.  Log packet/byte counts, source/destination address and other */
3955 /* protocol specific information.                                           */
3956 /* ------------------------------------------------------------------------ */
3957 void ipstate_log(is, type, ifs)
3958 struct ipstate *is;
3959 u_int type;
3960 ipf_stack_t *ifs;
3961 {
3962 #ifdef  IPFILTER_LOG
3963         struct  ipslog  ipsl;
3964         size_t sizes[1];
3965         void *items[1];
3966         int types[1];
 
 |