]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Merge branch 'master' into int-new
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 23 Jan 2018 17:29:32 +0000 (18:29 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Tue, 23 Jan 2018 17:29:32 +0000 (18:29 +0100)
1  2 
filter/filter.c
filter/filter.h
nest/rt-show.c
nest/rt-table.c
proto/bgp/bgp.h
proto/bgp/config.Y
proto/bgp/packets.c
sysdep/unix/io.c
sysdep/unix/krt.c

diff --cc filter/filter.c
index 4e17f9746a23e2804c4f2fba1b41e5e21e2c8c43,b0c560462c23cb7fa526b3712a5dac3a4d68c8ee..42e60a688a1b17a58443089cf1c049ab1df3fc01
@@@ -576,18 -587,11 +576,19 @@@ f_rta_cow(void
    (*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
  }
  
 +static char *
 +val_format_str(struct f_val v) {
 +  buffer b;
 +  LOG_BUFFER_INIT(b);
 +  val_format(v, &b);
 +  return lp_strdup(f_pool, b.start);
 +}
 +
  static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
  
 -#define runtime(x) do { \
 +#define runtime(fmt, ...) do { \
-     log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
+     if (!(f_flags & FF_SILENT)) \
 -      log_rl(&rl_runtime_err, L_ERR "filters, line %d: %s", what->lineno, x); \
++      log_rl(&rl_runtime_err, L_ERR "filters, line %d: " fmt, what->lineno, ##__VA_ARGS__); \
      res.type = T_RETURN; \
      res.val.i = F_ERROR; \
      return res; \
diff --cc filter/filter.h
index 89cd80e6d0b0ff374d98eed418de3d232041d52e,efb4b978cf091a81c0be3c1650bf813db961e5ae..49004c331652c1283a8eb725df9b7b4c1f3797e9
@@@ -208,16 -227,6 +208,17 @@@ struct f_tri
  #define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
  
  #define FF_FORCE_TMPATTR 1            /* Force all attributes to be temporary */
+ #define FF_SILENT 2                   /* Silent filter execution */
  
 +/* Bird Tests */
 +struct f_bt_test_suite {
 +  node n;                     /* Node in config->tests */
 +  struct f_inst *fn;          /* Root of function */
 +  const char *fn_name;                /* Name of test */
 +  const char *dsc;            /* Description */
 +};
 +
 +/* Hook for call bt_assert() function in configuration */
 +extern void (*bt_assert_hook)(int result, struct f_inst *assert);
 +
  #endif
diff --cc nest/rt-show.c
index 41a141a2602d6f8cf7d985041f5cebe9a551c6ce,0000000000000000000000000000000000000000..70dabc1f11883dc5dc3cd396697b1f3c46835af8
mode 100644,000000..100644
--- /dev/null
@@@ -1,421 -1,0 +1,422 @@@
-               (f_run(ec->out_filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) <= F_ACCEPT);
 +/*
 + *    BIRD -- Route Display Routines
 + *
 + *    (c) 1998--2000 Martin Mares <mj@ucw.cz>
 + *    (c) 2017       Jan Moskyto Matejka <mq@jmq.cz>
 + *
 + *    Can be freely distributed and used under the terms of the GNU GPL.
 + */
 +
 +#undef LOCAL_DEBUG
 +
 +#include "nest/bird.h"
 +#include "nest/route.h"
 +#include "nest/protocol.h"
 +#include "nest/cli.h"
 +#include "nest/iface.h"
 +#include "filter/filter.h"
 +
 +static void
 +rt_show_table(struct cli *c, struct rt_show_data *d)
 +{
 +  /* No table blocks in 'show route count' */
 +  if (d->stats == 2)
 +    return;
 +
 +  if (d->last_table) cli_printf(c, -1007, "");
 +  cli_printf(c, -1007, "Table %s:", d->tab->table->name);
 +  d->last_table = d->tab;
 +}
 +
 +static void
 +rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
 +{
 +  byte from[IPA_MAX_TEXT_LENGTH+8];
 +  byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
 +  rta *a = e->attrs;
 +  int primary = (e->net->routes == e);
 +  int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
 +  void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
 +  struct nexthop *nh;
 +
 +  tm_format_time(tm, &config->tf_route, e->lastmod);
 +  if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->nh.gw))
 +    bsprintf(from, " from %I", a->from);
 +  else
 +    from[0] = 0;
 +
 +  get_route_info = a->src->proto->proto->get_route_info;
 +  if (get_route_info || d->verbose)
 +    {
 +      /* Need to normalize the extended attributes */
 +      ea_list *t = tmpa;
 +      t = ea_append(t, a->eattrs);
 +      tmpa = alloca(ea_scan(t));
 +      ea_merge(t, tmpa);
 +      ea_sort(tmpa);
 +    }
 +  if (get_route_info)
 +    get_route_info(e, info, tmpa);
 +  else
 +    bsprintf(info, " (%d)", e->pref);
 +
 +  if (d->last_table != d->tab)
 +    rt_show_table(c, d);
 +
 +  cli_printf(c, -1007, "%-20s %s [%s %s%s]%s%s", ia, rta_dest_name(a->dest),
 +           a->src->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info);
 +
 +  if (a->dest == RTD_UNICAST)
 +    for (nh = &(a->nh); nh; nh = nh->next)
 +    {
 +      char mpls[MPLS_MAX_LABEL_STACK*12 + 5], *lsp = mpls;
 +      char *onlink = (nh->flags & RNF_ONLINK) ? " onlink" : "";
 +      char weight[16] = "";
 +
 +      if (nh->labels)
 +        {
 +        lsp += bsprintf(lsp, " mpls %d", nh->label[0]);
 +        for (int i=1;i<nh->labels; i++)
 +          lsp += bsprintf(lsp, "/%d", nh->label[i]);
 +      }
 +      *lsp = '\0';
 +
 +      if (a->nh.next)
 +      bsprintf(weight, " weight %d", nh->weight + 1);
 +
 +      if (ipa_nonzero(nh->gw))
 +      cli_printf(c, -1007, "\tvia %I on %s%s%s%s",
 +                 nh->gw, nh->iface->name, mpls, onlink, weight);
 +      else
 +      cli_printf(c, -1007, "\tdev %s%s%s",
 +                 nh->iface->name, mpls,  onlink, weight);
 +    }
 +
 +  if (d->verbose)
 +    rta_show(c, a, tmpa);
 +}
 +
 +static void
 +rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
 +{
 +  rte *e, *ee;
 +  byte ia[NET_MAX_TEXT_LENGTH+1];
 +  struct ea_list *tmpa;
 +  struct channel *ec = d->tab->export_channel;
 +  int first = 1;
 +  int pass = 0;
 +
 +  bsnprintf(ia, sizeof(ia), "%N", n->n.addr);
 +
 +  for (e = n->routes; e; e = e->next)
 +    {
 +      if (rte_is_filtered(e) != d->filtered)
 +      continue;
 +
 +      d->rt_counter++;
 +      d->net_counter += first;
 +      first = 0;
 +
 +      if (pass)
 +      continue;
 +
 +      ee = e;
 +      tmpa = rte_make_tmp_attrs(e, c->show_pool);
 +
 +      /* Export channel is down, do not try to export routes to it */
 +      if (ec && (ec->export_state == ES_DOWN))
 +      goto skip;
 +
 +      /* Special case for merged export */
 +      if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
 +        {
 +        rte *rt_free;
 +        e = rt_export_merged(ec, n, &rt_free, &tmpa, c->show_pool, 1);
 +        pass = 1;
 +
 +        if (!e)
 +        { e = ee; goto skip; }
 +      }
 +      else if (d->export_mode)
 +      {
 +        struct proto *ep = ec->proto;
 +        int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, c->show_pool) : 0;
 +
 +        if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED)
 +          pass = 1;
 +
 +        if (ic < 0)
 +          goto skip;
 +
 +        if (d->export_mode > RSEM_PREEXPORT)
 +          {
 +            /*
 +             * FIXME - This shows what should be exported according to current
 +             * filters, but not what was really exported. 'configure soft'
 +             * command may change the export filter and do not update routes.
 +             */
 +            int do_export = (ic > 0) ||
++              (f_run(ec->out_filter, &e, &tmpa, c->show_pool,
++                     FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
 +
 +            if (do_export != (d->export_mode == RSEM_EXPORT))
 +              goto skip;
 +
 +            if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_ACCEPTED))
 +              pass = 1;
 +          }
 +      }
 +
 +      if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
 +      goto skip;
 +
 +      if (f_run(d->filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
 +      goto skip;
 +
 +      if (d->stats < 2)
 +      rt_show_rte(c, ia, e, d, tmpa);
 +
 +      d->show_counter++;
 +      ia[0] = 0;
 +
 +    skip:
 +      if (e != ee)
 +      {
 +      rte_free(e);
 +      e = ee;
 +      }
 +      lp_flush(c->show_pool);
 +
 +      if (d->primary_only)
 +      break;
 +    }
 +}
 +
 +static void
 +rt_show_cleanup(struct cli *c)
 +{
 +  struct rt_show_data *d = c->rover;
 +  struct rt_show_data_rtable *tab;
 +
 +  /* Unlink the iterator */
 +  if (d->table_open)
 +    fit_get(&d->tab->table->fib, &d->fit);
 +
 +  /* Unlock referenced tables */
 +  WALK_LIST(tab, d->tables)
 +    rt_unlock_table(tab->table);
 +}
 +
 +static void
 +rt_show_cont(struct cli *c)
 +{
 +  struct rt_show_data *d = c->rover;
 +#ifdef DEBUGGING
 +  unsigned max = 4;
 +#else
 +  unsigned max = 64;
 +#endif
 +  struct fib *fib = &d->tab->table->fib;
 +  struct fib_iterator *it = &d->fit;
 +
 +  if (d->running_on_config && (d->running_on_config != config))
 +  {
 +    cli_printf(c, 8004, "Stopped due to reconfiguration");
 +    goto done;
 +  }
 +
 +  if (!d->table_open)
 +  {
 +    FIB_ITERATE_INIT(&d->fit, &d->tab->table->fib);
 +    d->table_open = 1;
 +    d->table_counter++;
 +
 +    d->show_counter_last = d->show_counter;
 +    d->rt_counter_last   = d->rt_counter;
 +    d->net_counter_last  = d->net_counter;
 +
 +    if (d->tables_defined_by & RSD_TDB_SET)
 +      rt_show_table(c, d);
 +  }
 +
 +  FIB_ITERATE_START(fib, it, net, n)
 +  {
 +    if (!max--)
 +    {
 +      FIB_ITERATE_PUT(it);
 +      return;
 +    }
 +    rt_show_net(c, n, d);
 +  }
 +  FIB_ITERATE_END;
 +
 +  if (d->stats)
 +  {
 +    if (d->last_table != d->tab)
 +      rt_show_table(c, d);
 +
 +    cli_printf(c, -1007, "%d of %d routes for %d networks in table %s",
 +             d->show_counter - d->show_counter_last, d->rt_counter - d->rt_counter_last,
 +             d->net_counter - d->net_counter_last, d->tab->table->name);
 +  }
 +
 +  d->table_open = 0;
 +  d->tab = NODE_NEXT(d->tab);
 +
 +  if (NODE_VALID(d->tab))
 +    return;
 +
 +  if (d->stats && (d->table_counter > 1))
 +  {
 +    if (d->last_table) cli_printf(c, -1007, "");
 +    cli_printf(c, 14, "Total: %d of %d routes for %d networks in %d tables",
 +             d->show_counter, d->rt_counter, d->net_counter, d->table_counter);
 +  }
 +  else
 +    cli_printf(c, 0, "");
 +
 +done:
 +  rt_show_cleanup(c);
 +  c->cont = c->cleanup = NULL;
 +}
 +
 +struct rt_show_data_rtable *
 +rt_show_add_table(struct rt_show_data *d, rtable *t)
 +{
 +  struct rt_show_data_rtable *tab = cfg_allocz(sizeof(struct rt_show_data_rtable));
 +  tab->table = t;
 +  add_tail(&(d->tables), &(tab->n));
 +  return tab;
 +}
 +
 +static inline void
 +rt_show_get_default_tables(struct rt_show_data *d)
 +{
 +  struct channel *c;
 +  struct rt_show_data_rtable *tab;
 +
 +  if (d->export_channel)
 +  {
 +    c = d->export_channel;
 +    tab = rt_show_add_table(d, c->table);
 +    tab->export_channel = c;
 +    return;
 +  }
 +
 +  if (d->export_protocol)
 +  {
 +    WALK_LIST(c, d->export_protocol->channels)
 +    {
 +      if (c->export_state == ES_DOWN)
 +      continue;
 +
 +      tab = rt_show_add_table(d, c->table);
 +      tab->export_channel = c;
 +    }
 +    return;
 +  }
 +
 +  if (d->show_protocol)
 +  {
 +    WALK_LIST(c, d->show_protocol->channels)
 +      rt_show_add_table(d, c->table);
 +    return;
 +  }
 +
 +  for (int i=1; i<NET_MAX; i++)
 +    if (config->def_tables[i])
 +      rt_show_add_table(d, config->def_tables[i]->table);
 +}
 +
 +static inline void
 +rt_show_prepare_tables(struct rt_show_data *d)
 +{
 +  struct rt_show_data_rtable *tab, *tabx;
 +
 +  /* Add implicit tables if no table is specified */
 +  if (EMPTY_LIST(d->tables))
 +    rt_show_get_default_tables(d);
 +
 +  WALK_LIST_DELSAFE(tab, tabx, d->tables)
 +  {
 +    /* Ensure there is defined export_channel for each table */
 +    if (d->export_mode)
 +    {
 +      if (!tab->export_channel && d->export_channel &&
 +        (tab->table == d->export_channel->table))
 +      tab->export_channel = d->export_channel;
 +
 +      if (!tab->export_channel && d->export_protocol)
 +      tab->export_channel = proto_find_channel_by_table(d->export_protocol, tab->table);
 +
 +      if (!tab->export_channel)
 +      {
 +      if (d->tables_defined_by & RSD_TDB_NMN)
 +        cf_error("No export channel for table %s", tab->table->name);
 +
 +      rem_node(&(tab->n));
 +      continue;
 +      }
 +    }
 +
 +    /* Ensure specified network is compatible with each table */
 +    if (d->addr && (tab->table->addr_type != d->addr->type))
 +    {
 +      if (d->tables_defined_by & RSD_TDB_NMN)
 +      cf_error("Incompatible type of prefix/ip for table %s", tab->table->name);
 +
 +      rem_node(&(tab->n));
 +      continue;
 +    }
 +  }
 +
 +  /* Ensure there is at least one table */
 +  if (EMPTY_LIST(d->tables))
 +    cf_error("No valid tables");
 +}
 +
 +void
 +rt_show(struct rt_show_data *d)
 +{
 +  struct rt_show_data_rtable *tab;
 +  net *n;
 +
 +  /* Filtered routes are neither exported nor have sensible ordering */
 +  if (d->filtered && (d->export_mode || d->primary_only))
 +    cf_error("Incompatible show route options");
 +
 +  rt_show_prepare_tables(d);
 +
 +  if (!d->addr)
 +  {
 +    WALK_LIST(tab, d->tables)
 +      rt_lock_table(tab->table);
 +
 +    /* There is at least one table */
 +    d->tab = HEAD(d->tables);
 +    this_cli->cont = rt_show_cont;
 +    this_cli->cleanup = rt_show_cleanup;
 +    this_cli->rover = d;
 +  }
 +  else
 +  {
 +    WALK_LIST(tab, d->tables)
 +    {
 +      d->tab = tab;
 +
 +      if (d->show_for)
 +      n = net_route(tab->table, d->addr);
 +      else
 +      n = net_find(tab->table, d->addr);
 +
 +      if (n)
 +      rt_show_net(this_cli, n, d);
 +    }
 +
 +    if (d->rt_counter)
 +      cli_msg(0, "");
 +    else
 +      cli_msg(8001, "Network not found");
 +  }
 +}
 +
diff --cc nest/rt-table.c
Simple merge
diff --cc proto/bgp/bgp.h
index 1310582b9d90074b2e447f9579e1b78b6c3dbf4f,b3db8b7e8e5568a329ce23d877a83ba7ce2fbada..30424abb852cc52fd7cd974554a3c4ff8b34397b
@@@ -118,8 -62,10 +118,9 @@@ struct bgp_config 
    unsigned error_delay_time_min;      /* Time to wait after an error is detected */
    unsigned error_delay_time_max;
    unsigned disable_after_error;               /* Disable the protocol when error is detected */
+   u32 disable_after_cease;            /* Disable it when cease is received, bitfield */
  
    char *password;                     /* Password used for MD5 authentication */
 -  struct rtable_config *igp_table;    /* Table used for recursive next hop lookups */
    int check_link;                     /* Use iface link state for liveness detection */
    int bfd;                            /* Use BFD for liveness detection */
  };
index 04e6d666759b94166d87f031647e9f1febe43dd3,075403a3fd0d67ed8ffe3057df729f5fe7729357..41eaa729bc9155a737756cae57ce2707d53d9202
@@@ -17,24 -16,28 +17,30 @@@ CF_DEFINE
  
  CF_DECLS
  
 -CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
 -      KEEPALIVE, MULTIHOP, STARTUP, VIA, NEXT, HOP, SELF, DEFAULT,
 -      PATH, METRIC, ERROR, START, DELAY, FORGET, WAIT, ENABLE,
 -      DISABLE, AFTER, BGP_PATH, BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN,
 -      BGP_NEXT_HOP, BGP_ATOMIC_AGGR, BGP_AGGREGATOR, BGP_COMMUNITY,
 -      BGP_EXT_COMMUNITY, SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT,
 -      CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE,
 -      PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
 -      INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
 -      TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY, DETERMINISTIC,
 -      SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX, GRACEFUL, RESTART, AWARE,
 -      CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY, BGP_LARGE_COMMUNITY)
 +CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY, KEEPALIVE,
 +      MULTIHOP, STARTUP, VIA, NEXT, HOP, SELF, DEFAULT, PATH, METRIC, ERROR,
 +      START, DELAY, FORGET, WAIT, ENABLE, DISABLE, AFTER, BGP_PATH,
 +      BGP_LOCAL_PREF, BGP_MED, BGP_ORIGIN, BGP_NEXT_HOP, BGP_ATOMIC_AGGR,
 +      BGP_AGGREGATOR, BGP_COMMUNITY, BGP_EXT_COMMUNITY, BGP_LARGE_COMMUNITY,
 +      SOURCE, ADDRESS, PASSWORD, RR, RS, CLIENT, CLUSTER, ID, AS4, ADVERTISE,
 +      IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER, MISSING, LLADDR,
 +      DROP, IGNORE, ROUTE, REFRESH, INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID,
 +      BGP_CLUSTER_LIST, IGP, TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL,
 +      SECURITY, DETERMINISTIC, SECONDARY, ALLOW, BFD, ADD, PATHS, RX, TX,
 +      GRACEFUL, RESTART, AWARE, CHECK, LINK, PORT, EXTENDED, MESSAGES, SETKEY,
 +      STRICT, BIND, CONFEDERATION, MEMBER, MULTICAST, FLOW4, FLOW6)
 +
 +%type <i32> bgp_afi
  
+ CF_KEYWORDS(CEASE, PREFIX, LIMIT, HIT, ADMINISTRATIVE, SHUTDOWN, RESET, PEER,
+       CONFIGURATION, CHANGE, DECONFIGURED, CONNECTION, REJECTED, COLLISION,
+       OUT, OF, RESOURCES)
+ %type<i> bgp_cease_mask bgp_cease_list bgp_cease_flag
  CF_GRAMMAR
  
 -CF_ADDTO(proto, bgp_proto '}' { bgp_check_config(BGP_CFG); } )
 +CF_ADDTO(proto, bgp_proto '}' )
  
  bgp_proto_start: proto_start BGP {
       this_proto = proto_config_new(&proto_bgp, $1);
index 95a974eb6335931ab3fb6b04c036dac9e862051f,f0049d3a56a665ca1fdc9b2ffe70fbec74121ab5..aa08732dc35fee8210bb8a77ed06fe23a8e88022
@@@ -2764,14 -1579,44 +2764,24 @@@ bgp_rx_notification(struct bgp_conn *co
    bgp_log_error(p, BE_BGP_RX, "Received", code, subcode, pkt+21, len-21);
    bgp_store_error(p, conn, BE_BGP_RX, (code << 16) | subcode);
  
 -#ifndef IPV6
 -  if ((code == 2) && ((subcode == 4) || (subcode == 7))
 -      /* Error related to capability:
 -       * 4 - Peer does not support capabilities at all.
 -       * 7 - Peer request some capability. Strange unless it is IPv6 only peer.
 -       */
 -      && (p->cf->capabilities == 2)
 -      /* Capabilities are not explicitly enabled or disabled, therefore heuristic is used */
 -      && (conn->start_state == BSS_CONNECT)
 -      /* Failed connection attempt have used capabilities */
 -      && (p->cf->remote_as <= 0xFFFF))
 -      /* Not possible with disabled capabilities */
 -    {
 -      /* We try connect without capabilities */
 -      log(L_WARN "%s: Capability related error received, retry with capabilities disabled", p->p.name);
 -      p->start_state = BSS_CONNECT_NOCAP;
 -      err = 0;
 -    }
 -#endif
 -
    bgp_conn_enter_close_state(conn);
 -  bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
 +  bgp_schedule_packet(conn, NULL, PKT_SCHEDULE_CLOSE);
  
 -  if (err) 
 -    {
 -      bgp_update_startup_delay(p);
 -      bgp_stop(p, 0, NULL, 0);
 -    }
 +  if (err)
 +  {
 +    bgp_update_startup_delay(p);
 +    bgp_stop(p, 0, NULL, 0);
 +  }
+   else
++  {
++    uint subcode_bit = 1 << ((subcode <= 8) ? subcode : 0);
++    if (p->cf->disable_after_cease & subcode_bit)
+     {
 -      uint subcode_bit = 1 << ((subcode <= 8) ? subcode : 0);
 -      if (p->cf->disable_after_cease & subcode_bit)
 -      {
 -      log(L_INFO "%s: Disabled after Cease notification", p->p.name);
 -      p->startup_delay = 0;
 -      p->p.disabled = 1;
 -      }
++      log(L_INFO "%s: Disabled after Cease notification", p->p.name);
++      p->startup_delay = 0;
++      p->p.disabled = 1;
+     }
++  }
  }
  
  static void
Simple merge
Simple merge