]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - proto/ospf/ospf.h
Merge branch 'master' into mq-filter-stack
[thirdparty/bird.git] / proto / ospf / ospf.h
index e3eae2b55171fda98edb730b12c38ed70698287f..beecd2b63bd2e8ca3dba793e02efe25ec3a9b3e8 100644 (file)
@@ -18,7 +18,7 @@
 #include "lib/lists.h"
 #include "lib/slists.h"
 #include "lib/socket.h"
-#include "sysdep/unix/timer.h"
+#include "lib/timer.h"
 #include "lib/resource.h"
 #include "nest/protocol.h"
 #include "nest/iface.h"
   log_rl(&p->log_lsa_tbf, L_REMOTE "%s: " msg, p->p.name, args)
 
 #define LOG_LSA2(msg, args...) \
-  do { if (! p->log_lsa_tbf.mark) \
+  do { if (! p->log_lsa_tbf.drop) \
     log(L_REMOTE "%s: " msg, p->p.name, args); } while(0)
 
 
 #define OSPF_PROTO 89
 
-#define LSREFRESHTIME 1800     /* 30 minutes */
-#define MINLSINTERVAL 5
-#define MINLSARRIVAL 1
-#define LSINFINITY 0xffffff
+#define LSREFRESHTIME          1800    /* 30 minutes */
+#define MINLSINTERVAL          (5 S_)
+#define MINLSARRIVAL           (1 S_)
+#define LSINFINITY             0xffffff
+
+#define OSPF_PKT_TYPES         5       /* HELLO_P .. LSACK_P */
+#define OSPF3_CRYPTO_ID                1       /* OSPFv3 Cryptographic Protocol ID */
 
 #define OSPF_DEFAULT_TICK 1
 #define OSPF_DEFAULT_STUB_COST 1000
 #define OSPF_DEFAULT_ECMP_LIMIT 16
+#define OSPF_DEFAULT_GR_TIME 120
 #define OSPF_DEFAULT_TRANSINT 40
 
 #define OSPF_MIN_PKT_SIZE 256
 
 #define OSPF_VLINK_ID_OFFSET 0x80000000
 
+#define OSPF_GR_ABLE           1
+#define OSPF_GR_AWARE          2
+
 struct ospf_config
 {
   struct proto_config c;
   uint tick;
   u8 ospf2;
+  u8 af_ext;
+  u8 af_mc;
   u8 rfc1583;
   u8 stub_router;
   u8 merge_external;
   u8 instance_id;
+  u8 instance_id_set;
   u8 abr;
   u8 asbr;
-  int ecmp;
+  u8 vpn_pe;
+  u8 gr_mode;                  /* Graceful restart mode (OSPF_GR_*) */
+  uint gr_time;                        /* Graceful restart interval */
+  uint ecmp;
   list area_list;              /* list of area configs (struct ospf_area_config) */
   list vlink_list;             /* list of configured vlinks (struct ospf_iface_patt) */
 };
@@ -168,9 +181,9 @@ struct ospf_iface_patt
   int tx_priority;
   u16 tx_length;
   u16 rx_buffer;
-
 #define OSPF_RXBUF_MINSIZE 256 /* Minimal allowed size */
   u8 instance_id;
+  u8 instance_id_set;
   u8 autype;                   /* OSPF_AUTH_*, not really used in OSPFv3 */
   u8 strictnbma;
   u8 check_link;
@@ -209,14 +222,24 @@ struct ospf_proto
   list area_list;              /* List of OSPF areas (struct ospf_area) */
   int areano;                  /* Number of area I belong to */
   int padj;                    /* Number of neighbors in Exchange or Loading state */
+  int gr_count;                        /* Number of neighbors in graceful restart state */
+  int gr_recovery;             /* Graceful restart recovery is active */
+  btime gr_timeout;            /* The end time of grace restart recovery */
   struct fib rtf;              /* Routing table */
   struct idm idm;              /* OSPFv3 LSA ID map */
-  byte ospf2;                  /* OSPF v2 or v3 */
-  byte rfc1583;                        /* RFC1583 compatibility */
-  byte stub_router;            /* Do not forward transit traffic */
-  byte merge_external;         /* Should i merge external routes? */
-  byte asbr;                   /* May i originate any ext/NSSA lsa? */
-  byte ecmp;                   /* Maximal number of nexthops in ECMP route, or 0 */
+  u8 ospf2;                    /* OSPF v2 or v3 */
+  u8 af_ext;                   /* OSPFv3-AF extension */
+  u8 af_mc;                    /* OSPFv3-AF multicast */
+  u8 rfc1583;                  /* RFC1583 compatibility */
+  u8 stub_router;              /* Do not forward transit traffic */
+  u8 merge_external;           /* Should i merge external routes? */
+  u8 instance_id;              /* Differentiate between more OSPF instances */
+  u8 asbr;                     /* May i originate any ext/NSSA lsa? */
+  u8 vpn_pe;                   /* Should we do VPN PE specific behavior (RFC 4577)? */
+  u8 ecmp;                     /* Maximal number of nexthops in ECMP route, or 0 */
+  u8 gr_mode;                  /* Graceful restart mode (OSPF_GR_*) */
+  uint gr_time;                        /* Graceful restart interval */
+  u64 csn64;                   /* Last used cryptographic sequence number */
   struct ospf_area *backbone;  /* If exists */
   event *flood_event;          /* Event for flooding LS updates */
   void *lsab;                  /* LSA buffer used when originating router LSAs */
@@ -249,8 +272,6 @@ struct ospf_area
   struct fib rtr;              /* Routing tables for routers */
 };
 
-
-
 struct ospf_iface
 {
   node n;
@@ -264,10 +285,10 @@ struct ospf_iface
   sock *sk;                    /* IP socket */
   list neigh_list;             /* List of neighbors (struct ospf_neighbor) */
   u32 cost;                    /* Cost of iface */
-  u32 waitint;                 /* number of sec before changing state from wait */
-  u32 rxmtint;                 /* number of seconds between LSA retransmissions */
-  u32 pollint;                 /* Poll interval */
-  u32 deadint;                 /* after "deadint" missing hellos is router dead */
+  u32 waitint;                 /* Number of seconds before changing state from wait */
+  u32 rxmtint;                 /* Number of seconds between LSA retransmissions */
+  u32 pollint;                 /* Poll interval in seconds */
+  u32 deadint;                 /* After deadint seconds without hellos is router dead */
   u32 iface_id;                        /* Interface ID (iface->index or new value for vlinks) */
   u32 vid;                     /* ID of peer of virtual link */
   ip_addr vip;                 /* IP of peer of virtual link */
@@ -278,8 +299,8 @@ struct ospf_iface
                                   interface.  LSAs contained in the update */
   u16 helloint;                        /* number of seconds between hello sending */
   list *passwords;
-  u32 csn;                      /* Last used crypt seq number */
-  bird_clock_t csn_use;         /* Last time when packet with that CSN was sent */
+  u32 csn;                     /* Last used crypt seq number */
+  btime csn_use;               /* Last time when packet with that CSN was sent */
   ip_addr all_routers;         /* Multicast (or broadcast) address for all routers */
   ip_addr des_routers;         /* Multicast (or NULL) address for designated routers */
   ip_addr drip;                        /* Designated router IP */
@@ -336,6 +357,8 @@ struct ospf_neighbor
   pool *pool;
   struct ospf_iface *ifa;
   u8 state;
+  u8 gr_active;                        /* We act as GR helper for the neighbor */
+  u8 got_my_rt_lsa;            /* Received my Rt-LSA in DBDES exchanged */
   timer *inactim;              /* Inactivity timer */
   u8 imms;                     /* I, M, Master/slave received */
   u8 myimms;                   /* I, M Master/slave */
@@ -345,7 +368,6 @@ struct ospf_neighbor
   u32 rid;                     /* Router ID */
   ip_addr ip;                  /* IP of it's interface */
   u8 priority;                 /* Priority */
-  u8 adj;                      /* built adjacency? */
   u32 options;                 /* Options received */
 
   /* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in
@@ -379,10 +401,12 @@ struct ospf_neighbor
 #define ACKL_DIRECT 0
 #define ACKL_DELAY 1
   timer *ackd_timer;           /* Delayed ack timer */
+  timer *gr_timer;             /* Graceful restart timer, non-NULL only if gr_active */
   struct bfd_request *bfd_req; /* BFD request, if BFD is used */
   void *ldd_buffer;            /* Last database description packet */
   u32 ldd_bsize;               /* Buffer size for ldd_buffer */
-  u32 csn;                      /* Last received crypt seq number (for MD5) */
+  u32 csn;                     /* OSPFv2: Last received crypt seq number */
+  u64 csn64[OSPF_PKT_TYPES];   /* OSPFv3: Last received CSN for each type of packet */
 };
 
 
@@ -417,6 +441,7 @@ struct ospf_neighbor
 #define OSPF_AUTH_SIMPLE 1
 #define OSPF_AUTH_CRYPT        2
 
+#define OSPF3_AUTH_HMAC 1      /* HMAC Cryptographic Authentication */
 
 /* OSPF neighbor states */
 #define NEIGHBOR_DOWN  0
@@ -449,14 +474,19 @@ struct ospf_neighbor
 
 
 /* Generic option flags */
-#define OPT_V6         0x01    /* OSPFv3, LSA relevant for IPv6 routing calculation */
-#define OPT_E          0x02    /* Related to AS-external LSAs */
-#define OPT_MC         0x04    /* Related to MOSPF, not used and obsolete */
-#define OPT_N          0x08    /* Related to NSSA */
-#define OPT_P          0x08    /* OSPFv2, flags P and N share position, see NSSA RFC */
-#define OPT_EA         0x10    /* OSPFv2, external attributes, not used and obsolete */
-#define OPT_R          0x10    /* OSPFv3, originator is active router */
-#define OPT_DC         0x20    /* Related to demand circuits, not used */
+#define OPT_V6         0x0001  /* OSPFv3, LSA relevant for IPv6 routing calculation */
+#define OPT_E          0x0002  /* Related to AS-external LSAs */
+#define OPT_MC         0x0004  /* Related to MOSPF, not used and obsolete */
+#define OPT_N          0x0008  /* Related to NSSA */
+#define OPT_P          0x0008  /* OSPFv2, flags P and N share position, see NSSA RFC */
+#define OPT_L_V2       0x0010  /* OSPFv2, link-local signaling, not used */
+#define OPT_R          0x0010  /* OSPFv3, originator is active router */
+#define OPT_DC         0x0020  /* Related to demand circuits, not used */
+#define OPT_O          0x0040  /* OSPFv2 Opaque LSA (RFC 5250) */
+#define OPT_DN         0x0080  /* OSPFv2 VPN loop prevention (RFC 4576)*/
+#define OPT_AF         0x0100  /* OSPFv3 Address Families (RFC 5838) */
+#define OPT_L_V3       0x0200  /* OSPFv3, link-local signaling */
+#define OPT_AT          0x0400 /* OSPFv3, authentication trailer */
 
 /* Router-LSA VEB flags are are stored together with links (OSPFv2) or options (OSPFv3) */
 #define OPT_RT_B       (0x01 << 24)
@@ -483,20 +513,38 @@ struct ospf_packet
   u8 autype;                   /* Undefined for OSPFv3 */
 };
 
+struct ospf_lls
+{
+  u16 checksum;
+  u16 length;
+  byte data[0];
+};
+
 struct ospf_auth_crypto
 {
   u16 zero;
   u8 keyid;
   u8 len;
-  u32 csn;
+  u32 csn;                     /* Cryptographic sequence number (32-bit) */
 };
 
-union ospf_auth
+union ospf_auth2
 {
   u8 password[8];
   struct ospf_auth_crypto c32;
 };
 
+struct ospf_auth3
+{
+  u16 type;                    /* Authentication type (OSPF3_AUTH_*) */
+  u16 length;                  /* Authentication trailer length (header + data) */
+  u16 reserved;
+  u16 sa_id;                   /* Security association identifier (key_id) */
+  u64 csn;                     /* Cryptographic sequence number (64-bit) */
+  byte data[0];                        /* Authentication data */
+};
+
+
 /* Packet types */
 #define HELLO_P                1       /* Hello */
 #define DBDES_P                2       /* Database description */
@@ -511,25 +559,46 @@ union ospf_auth
 #define DBDES_IMMS     (DBDES_I | DBDES_M | DBDES_MS)
 
 
-#define LSA_T_RT       0x2001
-#define LSA_T_NET      0x2002
-#define LSA_T_SUM_NET  0x2003
-#define LSA_T_SUM_RT   0x2004
-#define LSA_T_EXT      0x4005
-#define LSA_T_NSSA     0x2007
-#define LSA_T_LINK     0x0008
-#define LSA_T_PREFIX   0x2009
-
-#define LSA_T_V2_MASK  0x00ff
-
-#define LSA_UBIT       0x8000
-
-#define LSA_SCOPE_LINK 0x0000
-#define LSA_SCOPE_AREA 0x2000
-#define LSA_SCOPE_AS   0x4000
-#define LSA_SCOPE_RES  0x6000
-#define LSA_SCOPE_MASK 0x6000
-#define LSA_SCOPE(type)        ((type) & LSA_SCOPE_MASK)
+/* OSPFv3 LSA Types / LSA Function Codes */
+/* https://www.iana.org/assignments/ospfv3-parameters/ospfv3-parameters.xhtml#ospfv3-parameters-3 */
+#define LSA_T_RT               0x2001
+#define LSA_T_NET              0x2002
+#define LSA_T_SUM_NET          0x2003
+#define LSA_T_SUM_RT           0x2004
+#define LSA_T_EXT              0x4005
+#define LSA_T_NSSA             0x2007
+#define LSA_T_LINK             0x0008
+#define LSA_T_PREFIX           0x2009
+#define LSA_T_GR               0x000B
+#define LSA_T_RI_              0x000C
+#define LSA_T_RI_LINK          0x800C
+#define LSA_T_RI_AREA          0xA00C
+#define LSA_T_RI_AS            0xC00C
+#define LSA_T_OPAQUE_          0x1FFF
+#define LSA_T_OPAQUE_LINK      0x9FFF
+#define LSA_T_OPAQUE_AREA      0xBFFF
+#define LSA_T_OPAQUE_AS                0xDFFF
+
+#define LSA_T_V2_OPAQUE_       0x0009
+#define LSA_T_V2_MASK          0x00ff
+
+/* OSPFv2 Opaque LSA Types */
+/* https://www.iana.org/assignments/ospf-opaque-types/ospf-opaque-types.xhtml#ospf-opaque-types-2 */
+#define LSA_OT_GR              0x03
+#define LSA_OT_RI              0x04
+
+#define LSA_FUNCTION_MASK      0x1FFF
+#define LSA_FUNCTION(type)     ((type) & LSA_FUNCTION_MASK)
+
+#define LSA_UBIT               0x8000
+
+#define LSA_SCOPE_LINK         0x0000
+#define LSA_SCOPE_AREA         0x2000
+#define LSA_SCOPE_AS           0x4000
+#define LSA_SCOPE_RES          0x6000
+#define LSA_SCOPE_MASK         0x6000
+#define LSA_SCOPE(type)                ((type) & LSA_SCOPE_MASK)
+#define LSA_SCOPE_ORDER(type)  (((type) >> 13) & 0x3)
 
 
 #define LSA_MAXAGE     3600    /* 1 hour */
@@ -556,9 +625,26 @@ union ospf_auth
 #define LSA_EXT2_TOS   0x7F000000
 #define LSA_EXT2_EBIT  0x80000000
 
-#define LSA_EXT3_EBIT  0x4000000
-#define LSA_EXT3_FBIT  0x2000000
-#define LSA_EXT3_TBIT  0x1000000
+#define LSA_EXT3_EBIT  0x04000000
+#define LSA_EXT3_FBIT  0x02000000
+#define LSA_EXT3_TBIT  0x01000000
+
+/* OSPF Grace LSA (GR) TLVs */
+/* https://www.iana.org/assignments/ospfv2-parameters/ospfv2-parameters.xhtml#ospfv2-parameters-13 */
+#define LSA_GR_PERIOD          1
+#define LSA_GR_REASON          2
+#define LSA_GR_ADDRESS         3
+
+/* OSPF Router Information (RI) TLVs */
+/* https://www.iana.org/assignments/ospf-parameters/ospf-parameters.xhtml#ri-tlv */
+#define LSA_RI_RIC             1
+#define LSA_RI_RFC             2
+
+/* OSPF Router Informational Capability Bits */
+/* https://www.iana.org/assignments/ospf-parameters/ospf-parameters.xhtml#router-informational-capability */
+#define LSA_RIC_GR_CAPABLE     0
+#define LSA_RIC_GR_HELPER      1
+#define LSA_RIC_STUB_ROUTER    2
 
 
 struct ospf_lsa_header
@@ -675,7 +761,7 @@ struct ospf_lsa_ext_local
 {
   net_addr net;
   ip_addr fwaddr;
-  u32 metric, ebit, fbit, tag, propagate;
+  u32 metric, ebit, fbit, tag, propagate, downwards;
   u8 pxopts;
 };
 
@@ -701,6 +787,18 @@ struct ospf_lsa_prefix
   u32 rest[];
 };
 
+struct ospf_tlv
+{
+#ifdef CPU_BIG_ENDIAN
+  u16 type;
+  u16 length;
+#else
+  u16 length;
+  u16 type;
+#endif
+  u32 data[];
+};
+
 
 static inline uint
 lsa_net_count(struct ospf_lsa_header *lsa)
@@ -718,74 +816,96 @@ lsa_net_count(struct ospf_lsa_header *lsa)
 #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
 #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
 
-/* FIXME: these functions should be significantly redesigned w.r.t. integration,
-   also should be named as ospf3_* instead of *_ipv6_* */
 
 static inline int
 ospf_valid_prefix(net_addr *n)
 {
-  /* In OSPFv2, prefix is stored as netmask; ip4_masklen() returns 255 for invalid one */
-  return n->pxlen <= IP6_MAX_PREFIX_LENGTH;
+  /*
+   * In OSPFv2, prefix is stored as netmask; ip4_masklen() returns 255 for
+   * invalid one. But OSPFv3-AF may receive IPv4 net with 32 < pxlen < 128.
+   */
+  uint max = (n->type == NET_IP4) ? IP4_MAX_PREFIX_LENGTH : IP6_MAX_PREFIX_LENGTH;
+  return n->pxlen <= max;
 }
 
+/*
+ * In OSPFv3-AF (RFC 5835), IPv4 address is encoded by just placing it in the
+ * first 32 bits of IPv6 address and setting remaining bits to zero. Likewise
+ * for IPv4 prefix, where remaining bits do not matter. We use following
+ * functions to convert between IPv4 and IPv4-in-IPv6 representations:
+ */
+
+static inline ip4_addr ospf3_6to4(ip6_addr a)
+{ return _MI4(_I0(a)); }
+
+static inline ip6_addr ospf3_4to6(ip4_addr a)
+{ return _MI6(_I(a), 0, 0, 0); }
+
+
 static inline u32 *
-ospf_get_ipv6_prefix(u32 *buf, net_addr *N, u8 *pxopts, u16 *rest)
+ospf3_get_prefix(u32 *buf, int af, net_addr *n, u8 *pxopts, u16 *rest)
 {
-  net_addr_ip6 *net = (void *) N;
-  u8 pxlen = (*buf >> 24);
+  ip6_addr px = IP6_NONE;
+  uint pxlen = (*buf >> 24);
   *pxopts = (*buf >> 16) & 0xff;
   if (rest) *rest = *buf & 0xffff;
   buf++;
 
-  *net = NET_ADDR_IP6(IP6_NONE, pxlen);
-
   if (pxlen > 0)
-    _I0(net->prefix) = *buf++;
+    _I0(px) = *buf++;
   if (pxlen > 32)
-    _I1(net->prefix) = *buf++;
+    _I1(px) = *buf++;
   if (pxlen > 64)
-    _I2(net->prefix) = *buf++;
+    _I2(px) = *buf++;
   if (pxlen > 96)
-    _I3(net->prefix) = *buf++;
+    _I3(px) = *buf++;
 
   /* Clean up remaining bits */
   if (pxlen < 128)
-    net->prefix.addr[pxlen / 32] &= u32_mkmask(pxlen % 32);
+    px.addr[pxlen / 32] &= u32_mkmask(pxlen % 32);
 
-  return buf;
-}
+  if (af == NET_IP4)
+    net_fill_ip4(n, ospf3_6to4(px), pxlen);
+  else
+    net_fill_ip6(n, px, pxlen);
 
-static inline u32 *
-ospf_get_ipv6_addr(u32 *buf, ip_addr *addr)
-{
-  *addr = ipa_from_ip6(*(ip6_addr *) buf);
-  return buf + 4;
+  return buf;
 }
 
 static inline u32 *
-ospf_put_ipv6_prefix(u32 *buf, net_addr *N, u8 pxopts, u16 rest)
+ospf3_put_prefix(u32 *buf, net_addr *n, u8 pxopts, u16 rest)
 {
-  net_addr_ip6 *net = (void *) N;
-  u32 pxlen = net->pxlen;
+  ip6_addr px = (n->type == NET_IP4) ? ospf3_4to6(net4_prefix(n)) : net6_prefix(n);
+  uint pxlen = n->pxlen;
 
   *buf++ = ((pxlen << 24) | (pxopts << 16) | rest);
 
   if (pxlen > 0)
-    *buf++ = _I0(net->prefix);
+    *buf++ = _I0(px);
   if (pxlen > 32)
-    *buf++ = _I1(net->prefix);
+    *buf++ = _I1(px);
   if (pxlen > 64)
-    *buf++ = _I2(net->prefix);
+    *buf++ = _I2(px);
   if (pxlen > 96)
-    *buf++ = _I3(net->prefix);
+    *buf++ = _I3(px);
 
   return buf;
 }
 
 static inline u32 *
-ospf_put_ipv6_addr(u32 *buf, ip_addr addr)
+ospf3_get_addr(u32 *buf, int af, ip_addr *addr)
 {
-  *(ip6_addr *) buf = ipa_to_ip6(addr);
+  ip6_addr a;
+  memcpy(&a, buf, 16);
+  *addr = (af == NET_IP4) ? ipa_from_ip4(ospf3_6to4(a)) : ipa_from_ip6(a);
+  return buf + 4;
+}
+
+static inline u32 *
+ospf3_put_addr(u32 *buf, ip_addr addr)
+{
+  ip6_addr a = ipa_is_ip4(addr) ? ospf3_4to6(ipa_to_ip4(addr)) : ipa_to_ip6(addr);
+  memcpy(buf, &a, 16);
   return buf + 4;
 }
 
@@ -802,7 +922,7 @@ struct ospf_lsreq_header
 #define SH_ROUTER_SELF 0xffffffff
 
 struct lsadb_show_data {
-  struct symbol *name; /* Protocol to request data from */
+  struct ospf_proto *proto;    /* Protocol to request data from */
   u16 type;            /* LSA Type, 0 -> all */
   u16 scope;           /* Scope, 0 -> all, hack to handle link scope as 1 */
   u32 area;            /* Specified for area scope */
@@ -811,10 +931,10 @@ struct lsadb_show_data {
 };
 
 
-#define EA_OSPF_METRIC1        EA_CODE(EAP_OSPF, 0)
-#define EA_OSPF_METRIC2        EA_CODE(EAP_OSPF, 1)
-#define EA_OSPF_TAG    EA_CODE(EAP_OSPF, 2)
-#define EA_OSPF_ROUTER_ID EA_CODE(EAP_OSPF, 3)
+#define EA_OSPF_METRIC1        EA_CODE(PROTOCOL_OSPF, 0)
+#define EA_OSPF_METRIC2        EA_CODE(PROTOCOL_OSPF, 1)
+#define EA_OSPF_TAG    EA_CODE(PROTOCOL_OSPF, 2)
+#define EA_OSPF_ROUTER_ID EA_CODE(PROTOCOL_OSPF, 3)
 
 
 /* ospf.c */
@@ -838,6 +958,15 @@ static inline int ospf_is_v3(struct ospf_proto *p)
 static inline int ospf_get_version(struct ospf_proto *p)
 { return ospf_is_v2(p) ? 2 : 3; }
 
+static inline int ospf_is_ip4(struct ospf_proto *p)
+{ return p->p.net_type == NET_IP4; }
+
+static inline int ospf_is_ip6(struct ospf_proto *p)
+{ return p->p.net_type == NET_IP6; }
+
+static inline int ospf_get_af(struct ospf_proto *p)
+{ return p->p.net_type; }
+
 struct ospf_area *ospf_find_area(struct ospf_proto *p, u32 aid);
 
 static inline struct ospf_area *ospf_main_area(struct ospf_proto *p)
@@ -852,6 +981,8 @@ static inline int oa_is_ext(struct ospf_area *oa)
 static inline int oa_is_nssa(struct ospf_area *oa)
 { return oa->options & OPT_N; }
 
+void ospf_stop_gr_recovery(struct ospf_proto *p);
+
 void ospf_sh_neigh(struct proto *P, char *iff);
 void ospf_sh(struct proto *P);
 void ospf_sh_iface(struct proto *P, char *iff);
@@ -883,12 +1014,18 @@ static inline struct nbma_node * find_nbma_node(struct ospf_iface *ifa, ip_addr
 /* neighbor.c */
 struct ospf_neighbor *ospf_neighbor_new(struct ospf_iface *ifa);
 void ospf_neigh_sm(struct ospf_neighbor *n, int event);
+void ospf_neigh_cancel_graceful_restart(struct ospf_neighbor *n);
+void ospf_neigh_notify_grace_lsa(struct ospf_neighbor *n, struct top_hash_entry *en);
+void ospf_neigh_lsadb_changed_(struct ospf_proto *p, struct top_hash_entry *en);
 void ospf_dr_election(struct ospf_iface *ifa);
 struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
 struct ospf_neighbor *find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip);
 void ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd);
 void ospf_sh_neigh_info(struct ospf_neighbor *n);
 
+static inline void ospf_neigh_lsadb_changed(struct ospf_proto *p, struct top_hash_entry *en)
+{ if (p->gr_count) ospf_neigh_lsadb_changed_(p, en); }
+
 /* packet.c */
 void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
 int ospf_rx_hook(sock * sk, uint size);
@@ -920,7 +1057,7 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
 #endif
 
 static inline uint ospf_pkt_hdrlen(struct ospf_proto *p)
-{ return ospf_is_v2(p) ? (sizeof(struct ospf_packet) + sizeof(union ospf_auth)) : sizeof(struct ospf_packet); }
+{ return ospf_is_v2(p) ? (sizeof(struct ospf_packet) + sizeof(union ospf_auth2)) : sizeof(struct ospf_packet); }
 
 static inline void * ospf_tx_buffer(struct ospf_iface *ifa)
 { return ifa->sk->tbuf; }
@@ -932,11 +1069,14 @@ static inline void * ospf_tx_buffer(struct ospf_iface *ifa)
 
 void ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn);
 void ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr);
+uint ospf_hello3_options(struct ospf_packet *pkt);
 
 /* dbdes.c */
 void ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n);
 void ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n);
+void ospf_reset_ldd(struct ospf_proto *p, struct ospf_neighbor *n);
 void ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n);
+uint ospf_dbdes3_options(struct ospf_packet *pkt);
 
 /* lsreq.c */
 void ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n);