]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Md5 authentification added (unsested).
authorOndrej Filip <feela@network.cz>
Sat, 26 Jun 2004 20:15:34 +0000 (20:15 +0000)
committerOndrej Filip <feela@network.cz>
Sat, 26 Jun 2004 20:15:34 +0000 (20:15 +0000)
Packet receiving clean up.

13 files changed:
proto/ospf/config.Y
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/neighbor.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h
proto/ospf/rt.c

index b484d79c34afbf666f2984615e6b3cc12207cc54..f6ad5bc30e351ac0cc42b1e31ca472f2008eee50 100644 (file)
@@ -24,7 +24,7 @@ CF_DECLS
 CF_KEYWORDS(OSPF, AREA, OSPF_METRIC1, OSPF_METRIC2, OSPF_TAG)
 CF_KEYWORDS(NEIGHBORS, RFC1583COMPAT, STUB, TICK, COST, RETRANSMIT)
 CF_KEYWORDS(HELLO, TRANSMIT, PRIORITY, DEAD, NONBROADCAST, POINTOPOINT, TYPE)
-CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, PASSWORD, STRICT)
+CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT)
 CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, LINK)
 
 %type <t> opttext
@@ -96,9 +96,9 @@ ospf_vlink_item:
  | TRANSMIT DELAY expr { OSPF_PATT->inftransdelay = $3 ; if (($3<=0) || ($3>65535)) cf_error("Transmit delay must be in range 1-65535"); }
  | WAIT expr { OSPF_PATT->waitint = $2 ; }
  | DEAD COUNT expr { OSPF_PATT->deadc = $3 ; if ($3<=1) cf_error("Dead count must be greater than one"); }
- | AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
- | AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
- | PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
+ | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
+ | password_list {OSPF_PATT->passwords = $1; }
  ;
 
 ospf_vlink_start: VIRTUAL LINK '{'
@@ -114,7 +114,7 @@ ospf_vlink_start: VIRTUAL LINK '{'
   OSPF_PATT->waitint = WAIT_DMH*HELLOINT_D;
   OSPF_PATT->deadc = DEADC_D;
   OSPF_PATT->type = OSPF_IT_VLINK;
-  OSPF_PATT->autype = AU_NONE;
+  OSPF_PATT->autype = OSPF_AUTH_NONE;
  }
 ;
 
@@ -133,9 +133,9 @@ ospf_iface_item:
  | STRICT NONBROADCAST bool { OSPF_PATT->strictnbma = $3 ; }
  | STUB bool { OSPF_PATT->stub = $2 ; }
  | NEIGHBORS '{' ipa_list '}'
- | AUTHENTICATION NONE { OSPF_PATT->autype = AU_NONE ; }
- | AUTHENTICATION SIMPLE { OSPF_PATT->autype = AU_SIMPLE ; }
- | PASSWORD TEXT { memcpy(OSPF_PATT->password, $2, 8); }
+ | AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE ; }
+ | AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE ; }
+ | password_list {OSPF_PATT->passwords = $1; }
  ;
 
 pref_list:
@@ -210,7 +210,7 @@ ospf_iface_start:
   OSPF_PATT->strictnbma = 0;
   OSPF_PATT->stub = 0;
   init_list(&OSPF_PATT->nbma_list);
-  OSPF_PATT->autype = AU_NONE;
+  OSPF_PATT->autype = OSPF_AUTH_NONE;
  }
 ;
 
index c345858bb4272f8db714384ca56ecf21eaaf3f52..7bc87c50b2533e1dc015e838dcf581adc8db3f76 100644 (file)
@@ -38,15 +38,14 @@ ospf_dbdes_send(struct ospf_neighbor *n)
     n->myimms.bit.i = 1;
     pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
     op = (struct ospf_packet *) pkt;
-    fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
+    ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
     pkt->iface_mtu = htons(ifa->iface->mtu);
     pkt->options = ifa->options;
     pkt->imms = n->myimms;
     pkt->ddseq = htonl(n->dds);
     length = sizeof(struct ospf_dbdes_packet);
     op->length = htons(length);
-    ospf_pkt_finalize(ifa, op);
-    ospf_send_to(ifa->ip_sk, length, n->ip);
+    ospf_send_to(ifa->ip_sk, n->ip, ifa);
     OSPF_TRACE(D_PACKETS, "DB_DES (I) sent to %I via %s.", n->ip,
               ifa->iface->name);
     break;
@@ -63,12 +62,12 @@ ospf_dbdes_send(struct ospf_neighbor *n)
       pkt = n->ldbdes;
       op = (struct ospf_packet *) pkt;
 
-      fill_ospf_pkt_hdr(ifa, pkt, DBDES_P);
+      ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
       pkt->iface_mtu = htons(ifa->iface->mtu);
       pkt->options = ifa->options;
       pkt->ddseq = htonl(n->dds);
 
-      j = i = (ifa->iface->mtu - sizeof(struct ospf_dbdes_packet) - SIPH) / sizeof(struct ospf_lsa_header);    /* Number of possible lsaheaders to send */
+      j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header);     /* Number of possible lsaheaders to send */
       lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
 
       if (n->myimms.bit.m)
@@ -117,7 +116,6 @@ ospf_dbdes_send(struct ospf_neighbor *n)
        sizeof(struct ospf_dbdes_packet);
       op->length = htons(length);
 
-      ospf_pkt_finalize(ifa, op);
       DBG("%s: DB_DES (M) prepared for %I.\n", p->name, n->ip);
     }
 
@@ -136,7 +134,7 @@ ospf_dbdes_send(struct ospf_neighbor *n)
     memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
     /* Copy last sent packet again */
 
-    ospf_send_to(ifa->ip_sk, length, n->ip);
+    ospf_send_to(ifa->ip_sk, n->ip, n->ifa);
 
     if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint);             /* Restart timer */
 
index c805973092cfdb8ec8e2b590284405981e8c0bd5..b6d04ee47cc90c18415809b291d46515148d1a00 100644 (file)
@@ -200,7 +200,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   /* Now fill ospf_hello header */
   op = (struct ospf_packet *) pkt;
 
-  fill_ospf_pkt_hdr(ifa, pkt, HELLO_P);
+  ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
 
   pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
   ipa_hton(pkt->netmask);
@@ -218,6 +218,11 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
   WALK_LIST(neigh, ifa->neigh_list)
   {
+    if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_maxsize(ifa))
+    {
+      OSPF_TRACE(D_PACKETS, "Too many neighbors on the interface!");
+      break;
+    }
     *(pp + i) = htonl(neigh->rid);
     i++;
   }
@@ -225,15 +230,12 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
   length = sizeof(struct ospf_hello_packet) + i * sizeof(u32);
   op->length = htons(length);
 
-  ospf_pkt_finalize(ifa, op);
-
-  /* And finally send it :-) */
   switch(ifa->type)
   {
     case OSPF_IT_NBMA:
       if (timer == NULL)               /* Response to received hello */
       {
-        ospf_send_to(ifa->ip_sk, length, dirn->ip);
+        ospf_send_to(ifa->ip_sk, dirn->ip, ifa);
       }
       else
       {
@@ -258,7 +260,7 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
           if ((poll == 1) && (send))
           {
             if (toall || (meeli && nb->eligible))
-              ospf_send_to(ifa->ip_sk, length, nb->ip);
+              ospf_send_to(ifa->ip_sk, nb->ip, ifa);
           }
         }
         if (poll == 0)
@@ -267,16 +269,16 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
           {
             if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
                 (meeli && (n1->priority > 0)))
-              ospf_send_to(ifa->ip_sk, length, n1->ip);
+              ospf_send_to(ifa->ip_sk, n1->ip, ifa);
           }
         }
       }
       break;
     case OSPF_IT_VLINK:
-      ospf_send_to(ifa->ip_sk, length, ifa->vip);
+      ospf_send_to(ifa->ip_sk, ifa->vip, ifa);
       break;
     default:
-      sk_send(ifa->hello_sk, length);
+      ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
   }
   OSPF_TRACE(D_PACKETS, "Hello sent via %s", ifa->iface->name);
 }
index bd8cddd96044eac64f0c25c26588b118569b82e4..054ea7c1d2566ff37e9e4d689bd32485eb28433b 100644 (file)
@@ -373,7 +373,7 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ospf_area_conf
   ifa->deadc = ip->deadc;
   ifa->stub = ip->stub;
   ifa->autype = ip->autype;
-  memcpy(ifa->aukey, ip->password, 8);
+  ifa->passwords = ip->passwords;
   ifa->options = 2;            /* FIXME what options? */
 
   if (ip->type == OSPF_IT_UNDEF)
index bdad8665986b07004ba0d2a1ba3272aa96f54453..14832b8205c7487f7459a6502b2ab62b6531db93 100644 (file)
@@ -52,7 +52,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
   pk = (struct ospf_lsack_packet *) sk->tbuf;
   op = (struct ospf_packet *) sk->tbuf;
 
-  fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
+  ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
   h = (struct ospf_lsa_header *) (pk + 1);
 
   while (!EMPTY_LIST(n->ackl[queue]))
@@ -65,7 +65,7 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
     rem_node(NODE no);
     mb_free(no);
     if ((i * sizeof(struct ospf_lsa_header) +
-        sizeof(struct ospf_lsack_packet) + SIPH) > n->ifa->iface->mtu)
+        sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
     {
       if (!EMPTY_LIST(n->ackl[queue]))
       {
@@ -73,24 +73,23 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
          sizeof(struct ospf_lsack_packet) +
          i * sizeof(struct ospf_lsa_header);
        op->length = htons(len);
-       ospf_pkt_finalize(n->ifa, op);
        DBG("Sending and continuing! Len=%u\n", len);
        if (ifa->type == OSPF_IT_BCAST)
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           ospf_send_to(sk, len, AllSPFRouters);
+           ospf_send_to(sk, AllSPFRouters, ifa);
          else
-           ospf_send_to(sk, len, AllDRouters);
+           ospf_send_to(sk, AllDRouters, ifa);
        }
        else
        {
          if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
-           ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+           ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
          else
-           ospf_send_to_bdr(sk, len, ifa);
+           ospf_send_to_bdr(sk, ifa);
        }
 
-       fill_ospf_pkt_hdr(n->ifa, pk, LSACK_P);
+       ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
        i = 0;
       }
     }
@@ -98,22 +97,21 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
 
   len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header);
   op->length = htons(len);
-  ospf_pkt_finalize(n->ifa, op);
   DBG("Sending! Len=%u\n", len);
   if (ifa->type == OSPF_IT_BCAST)
   {
     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
     {
-      ospf_send_to(sk, len, AllSPFRouters);
+      ospf_send_to(sk, AllSPFRouters, ifa);
     }
     else
     {
-      ospf_send_to(sk, len, AllDRouters);
+      ospf_send_to(sk, AllDRouters, ifa);
     }
   }
   else
   {
-    ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+    ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
   }
 }
 
index 23622fc45bff9d7e3549c22146ae5c43b0b6e3e8..64f108271613834f03235470fc79106b5f9ef3e1 100644 (file)
@@ -23,7 +23,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
   pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf;
   op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
 
-  fill_ospf_pkt_hdr(n->ifa, pk, LSREQ_P);
+  ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
 
   sn = SHEAD(n->lsrql);
   if (EMPTY_SLIST(n->lsrql))
@@ -33,7 +33,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
     return;
   }
 
-  i = j = (n->ifa->iface->mtu - SIPH - sizeof(struct ospf_lsreq_packet)) /
+  i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
     sizeof(struct ospf_lsreq_header);
   lsh = (struct ospf_lsreq_header *) (pk + 1);
 
@@ -59,8 +59,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
     sizeof(struct ospf_lsreq_packet) + (j -
                                        i) * sizeof(struct ospf_lsreq_header);
   op->length = htons(length);
-  ospf_pkt_finalize(n->ifa, op);
-  ospf_send_to(n->ifa->ip_sk, length, n->ip);
+  ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
   OSPF_TRACE(D_PACKETS, "LS request sent to: %I", n->rid);
 }
 
index 0cefdd132bdb9d8acd2d2132b3474d4a86eea426..44d35d9713dc1cfe8ee92adc480432acf8504428 100644 (file)
@@ -160,7 +160,7 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
       pk = (struct ospf_lsupd_packet *) sk->tbuf;
       op = (struct ospf_packet *) sk->tbuf;
 
-      fill_ospf_pkt_hdr(ifa, pk, LSUPD_P);
+      ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
       pk->lsano = htonl(1);
 
       lh = (struct ospf_lsa_header *) (pk + 1);
@@ -191,23 +191,22 @@ ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn,
       lh->age = htons(age);
 
       op->length = htons(len);
-      ospf_pkt_finalize(ifa, op);
       OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name);
 
       if (ifa->type == OSPF_IT_NBMA)
       {
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
-         ospf_send_to_agt(sk, len, ifa, NEIGHBOR_EXCHANGE);
+         ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
        else
-         ospf_send_to_bdr(sk, len, ifa);
+         ospf_send_to_bdr(sk, ifa);
       }
       else
       {
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
            (ifa->type == OSPF_IT_PTP))
-         ospf_send_to(sk, len, AllSPFRouters);
+         ospf_send_to(sk, AllSPFRouters, ifa);
        else
-         ospf_send_to(sk, len, AllDRouters);
+         ospf_send_to(sk, AllDRouters, ifa);
       }
     }
   }
@@ -234,8 +233,8 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
 
   DBG("LSupd: 1st packet\n");
 
-  fill_ospf_pkt_hdr(n->ifa, pk, LSUPD_P);
-  len = SIPH + sizeof(struct ospf_lsupd_packet);
+  ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
+  len = sizeof(struct ospf_lsupd_packet);
   lsano = 0;
   pktpos = (pk + 1);
 
@@ -247,18 +246,17 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
 
     DBG("Sending ID=%I, Type=%u, RT=%I Sn: 0x%x Age: %u\n",
        llsh->lsh.id, llsh->lsh.type, llsh->lsh.rt, en->lsa.sn, en->lsa.age);
-    if (((u32) (len + en->lsa.length)) > n->ifa->iface->mtu)
+    if (((u32) (len + en->lsa.length)) > ospf_pkt_maxsize(n->ifa))
     {
       pk->lsano = htonl(lsano);
-      op->length = htons(len - SIPH);
-      ospf_pkt_finalize(n->ifa, op);
+      op->length = htons(len);
 
-      ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
+      ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
       OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
 
       DBG("LSupd: next packet\n");
-      fill_ospf_pkt_hdr(n->ifa, pk, LSUPD_P);
-      len = SIPH + sizeof(struct ospf_lsupd_packet);
+      ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
+      len = sizeof(struct ospf_lsupd_packet);
       lsano = 0;
       pktpos = (pk + 1);
     }
@@ -273,11 +271,10 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
   if (lsano > 0)
   {
     pk->lsano = htonl(lsano);
-    op->length = htons(len - SIPH);
-    ospf_pkt_finalize(n->ifa, op);
+    op->length = htons(len);
 
     OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano);
-    ospf_send_to(n->ifa->ip_sk, len - SIPH, n->ip);
+    ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
   }
 }
 
index 5abaf4820e0be2ea1dc5494897b8aaf72dc86fc0..e9ef476112f11b3b6f9d60c484db662fa38e0e9e 100644 (file)
@@ -41,6 +41,7 @@ ospf_neighbor_new(struct ospf_iface *ifa)
   n->ifa = ifa;
   add_tail(&ifa->neigh_list, NODE n);
   n->adj = 0;
+  n->csn = 0;
   n->ldbdes = mb_allocz(pool, ifa->iface->mtu);
   n->state = NEIGHBOR_DOWN;
 
index a1049e1be7c66d3ffdf2dc93d5a56dbb86d636a5..d948d652c3664a7b95556c191f43a2c4d358fbef 100644 (file)
@@ -675,12 +675,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
                     "Changing authentication type on interface %s",
                     ifa->iface->name);
        }
-       if (strncmp(ip1->password, ip2->password, 8) != 0)
-       {
-         memcpy(ifa->aukey, ip2->password, 8);
-         OSPF_TRACE(D_EVENTS,
-                    "Changing password on interface %s", ifa->iface->name);
-       }
+        /* FIXME Add *passwords */
 
        /* RXMT */
        if (ip1->rxmtint != ip2->rxmtint)
index d1de12adfe7cb378c198a7ed08d14e3f54bc6caf..2a499f751bc16b588c11d58f5ffb404d760fa18c 100644 (file)
@@ -9,7 +9,6 @@
 #ifndef _BIRD_OSPF_H_
 #define _BIRD_OSPF_H_
 
-#define SIPH SIZE_OF_IP_HEADER
 #define MAXNETS 10
 #ifdef LOCAL_DEBUG
 #define OSPF_FORCE_DEBUG 1
@@ -122,8 +121,9 @@ struct ospf_iface
   ip_addr vip;                 /* IP of peer of virtual link */
   struct ospf_area *voa;       /* Area wich the vlink goes through */
   u16 autype;
-  u8 aukey[8];
   u8 options;
+  list *passwords;
+  u32 csn;                      /* Crypt seq num. that will be sent net */
   ip_addr drip;                        /* Designated router */
   u32 drid;
   ip_addr bdrip;               /* Backup DR */
@@ -168,6 +168,20 @@ struct ospf_iface
   list nbma_list;
 };
 
+struct ospf_md5
+{
+  u16 zero;
+  u8 keyid;
+  u8 len;
+  u32 csn;
+};
+
+union ospf_auth
+{
+  u8 password[8];
+  struct ospf_md5 md5;
+};
+
 struct ospf_packet
 {
   u8 version;
@@ -183,7 +197,7 @@ struct ospf_packet
 #define BACKBONE 0
   u16 checksum;
   u16 autype;
-  u8 authetication[8];
+  union ospf_auth u;
 };
 
 struct ospf_hello_packet
@@ -437,6 +451,7 @@ struct ospf_neighbor
 #define ACKL_DIRECT 0
 #define ACKL_DELAY 1
   timer *ackd_timer;           /* Delayed ack timer */
+  u32 csn;                      /* Last received crypt seq number (for MD5) */
 };
 
 /* Definitions for interface state machine */
@@ -512,11 +527,11 @@ struct ospf_iface_patt
   u32 strictnbma;
   u32 stub;
   u32 vid;
-/* must be in network byte order */
-#define AU_NONE htons(0)
-#define AU_SIMPLE htons(1)
-#define AU_CRYPT htons(2)
-  u8 password[8];
+#define OSPF_AUTH_NONE 0
+#define OSPF_AUTH_SIMPLE 1
+#define OSPF_AUTH_CRYPT 2
+#define OSPF_AUTH_CRYPT_SIZE 16
+  list *passwords;
   list nbma_list;
 };
 
index 4f5db664762e99785b71c458f4d5d99833f2823e..9334e59578461f8e02892214ed857a551d11a153 100644 (file)
@@ -1,15 +1,17 @@
 /*
  *     BIRD -- OSPF
  *
- *     (c) 1999 - 2003 Ondrej Filip <feela@network.cz>
+ *     (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
 #include "ospf.h"
+#include "nest/password.h"
+#include "lib/md5.h"
 
 void
-fill_ospf_pkt_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
+ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 {
   struct ospf_packet *pkt;
   struct proto *p;
@@ -28,45 +30,167 @@ fill_ospf_pkt_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
   pkt->checksum = 0;
 }
 
+unsigned
+ospf_pkt_maxsize(struct ospf_iface *ifa)
+{
+  return ifa->iface->mtu - SIZE_OF_IP_HEADER -
+    ((ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0);
+}
+
 void
-ospf_tx_authenticate(struct ospf_iface *ifa, struct ospf_packet *pkt)
+ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
 {
+  struct proto_ospf *po = ifa->proto;
+  struct proto *p = &po->proto;
+  struct password_item *passwd = password_find (ifa->passwords);
+  void *tail;
+  struct MD5Context ctxt;
+  char password[OSPF_AUTH_CRYPT_SIZE];
+
   pkt->autype = htons(ifa->autype);
-  memcpy(pkt->authetication, ifa->aukey, 8);
-  return;
+
+  switch(ifa->autype)
+  {
+    case OSPF_AUTH_NONE:
+    case OSPF_AUTH_SIMPLE:
+      pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) - 8,
+                                 (pkt + 1),
+                                 ntohs(pkt->length) -
+                                 sizeof(struct ospf_packet), NULL);
+      password_cpy(pkt->u.password, passwd->password, 8);
+      break;
+    case OSPF_AUTH_CRYPT:
+      if (!passwd)
+      {
+        log( L_ERR "No suitable password found for authentication" );
+        return;
+      }
+
+      pkt->checksum = 0;
+
+      if (!ifa->csn)
+        ifa->csn = (u32) time(NULL);
+
+      pkt->u.md5.keyid = passwd->id;
+      pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE;
+      pkt->u.md5.zero = 0;
+      pkt->u.md5.csn = htonl(ifa->csn++);
+      tail = ((void *)pkt) + ntohs(pkt->length);
+      MD5Init(&ctxt);
+      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
+      password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
+      MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
+      MD5Final(tail, &ctxt);
+      
+      break;
+    default:
+      bug("Unknown authentication type");
+  }
 }
 
 static int
-ospf_rx_authenticate(struct ospf_iface *ifa, struct ospf_packet *pkt)
+ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_packet *pkt, int size)
 {
   int i;
+  struct ospf_iface *ifa = n->ifa;
+  struct proto_ospf *po = ifa->proto;
+  struct proto *p = &po->proto;
+  struct password_item *pass = NULL, *ptmp;
+  void *tail;
+  char md5sum[OSPF_AUTH_CRYPT_SIZE];
+  char password[OSPF_AUTH_CRYPT_SIZE];
+  struct MD5Context ctxt;
+
+
   if (pkt->autype != htons(ifa->autype))
-    return 0;
-  if (ifa->autype == AU_NONE)
-    return 1;
-  if (ifa->autype == AU_SIMPLE)
   {
-    for (i = 0; i < 8; i++)
-    {
-      if (pkt->authetication[i] != ifa->aukey[i])
-       return 0;
-    }
-    return 1;
+    OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype));
+    return 0;
   }
-  return 0;
-}
 
-void
-ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
-{
-
-  ospf_tx_authenticate(ifa, pkt);
+  switch(ifa->autype)
+  {
+    case OSPF_AUTH_NONE:
+      return 1;
+      break;
+    case OSPF_AUTH_SIMPLE:
+      pass = password_find (ifa->passwords);
+      if(!pass)
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found");
+       return 0;
+      }
 
-  /* Count checksum */
-  pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) - 8,
-                                 (pkt + 1),
-                                 ntohs(pkt->length) -
-                                 sizeof(struct ospf_packet), NULL);
+      if (memcmp(pkt->u.password,pass, 8))
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords");
+       return 0;
+      }
+
+      else
+        return 1;
+      break;
+    case OSPF_AUTH_CRYPT:
+      if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE)
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
+        return 0;
+      }
+      if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE != size)
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch");
+        return 0;
+      }
+
+      if (pkt->u.md5.zero)
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: \"zero\" area is non-zero");
+        return 0;
+      }
+
+      tail = ((void *)pkt) + ntohs(pkt->length);
+
+      WALK_LIST(ptmp, *(ifa->passwords))
+      {
+        if (pkt->u.md5.keyid != pass->id) continue;
+        if ((pass->genfrom > now) || (pass->gento < now)) continue;
+        pass = ptmp;
+        break;
+      }
+
+      if(!pass)
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found");
+        return 0;
+      }
+
+      if(n)
+      {
+        if(ntohs(pkt->u.md5.csn) <= n->csn)
+        {
+          OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number");
+          return 0;
+        }
+
+        n->csn = ntohs(pkt->u.md5.csn);
+      }
+
+      MD5Init(&ctxt);
+      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
+      password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
+      MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
+      MD5Final(md5sum, &ctxt);
+      if (!memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
+      {
+        OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
+        return 0;
+      }
+      return 1;
+      break;
+    default:
+      OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
+      return 0;
+  }
 }
 
 /**
@@ -119,19 +243,13 @@ ospf_rx_hook(sock * sk, int size)
     return 1;
   }
 
-  if (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
-                   ntohs(ps->length) - sizeof(struct ospf_packet), NULL))
+  if ((ifa->autype != OSPF_AUTH_CRYPT) && (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
+                   ntohs(ps->length) - sizeof(struct ospf_packet), NULL)))
   {
     log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
     return 1;
   }
 
-  if (!ospf_rx_authenticate(ifa, ps))
-  {
-    log(L_ERR "%s%I - bad password", mesg, sk->faddr);
-    return 1;
-  }
-
   if (ntohl(ps->areaid) != ifa->an)
   {
     log(L_ERR "%s%I - other area %ld", mesg, sk->faddr, ps->areaid);
@@ -164,6 +282,12 @@ ospf_rx_hook(sock * sk, int size)
     return 1;
   }
 
+  if (!ospf_pkt_checkauth(n, ps, size))
+  {
+    log(L_ERR "%s%I - authentification failed", mesg, sk->faddr);
+    return 1;
+  }
+
   /* Dump packet 
      pu8=(u8 *)(sk->rbuf+5*4);
      for(i=0;i<ntohs(ps->length);i+=4)
@@ -226,26 +350,33 @@ ospf_err_hook(sock * sk, int err UNUSED)
 }
 
 void
-ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state)
+ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
 {
   struct ospf_neighbor *n;
 
   WALK_LIST(NODE n, ifa->neigh_list) if (n->state >= state)
-    ospf_send_to(sk, len, n->ip);
+    ospf_send_to(sk, n->ip, ifa);
 }
 
 void
-ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa)
+ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa)
 {
   if (ipa_compare(ifa->drip, ipa_from_u32(0)) != 0)
-    ospf_send_to(sk, len, ifa->drip);
+    ospf_send_to(sk, ifa->drip, ifa);
   if (ipa_compare(ifa->bdrip, ipa_from_u32(0)) != 0)
-    ospf_send_to(sk, len, ifa->bdrip);
+    ospf_send_to(sk, ifa->bdrip, ifa);
 }
 
 void
-ospf_send_to(sock *sk, u16 len, ip_addr ip)
+ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa)
 {
-  sk_send_to(sk, len, ip, OSPF_PROTO);
+  struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
+  int len = ntohs(pkt->length) + (pkt->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
+  ospf_pkt_finalize(ifa, pkt);
+
+  if (ipa_equal(ip, IPA_NONE))
+    sk_send(sk, len);
+  else
+    sk_send_to(sk, len, ip, OSPF_PROTO);
 }
 
index 0742adfa42b22dd9a76cdab90a82f3b1a1d0a3c6..b85b608b52cf6104c3e84f502c5a6eca7c2aac57 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *      BIRD -- OSPF
  *
- *      (c) 1999 - 2000 Ondrej Filip <feela@network.cz>
+ *      (c) 1999--2004 Ondrej Filip <feela@network.cz>
  *
  *      Can be freely distributed and used under the terms of the GNU GPL.
  *
 #ifndef _BIRD_OSPF_PACKET_H_
 #define _BIRD_OSPF_PACKET_H_
 
-void fill_ospf_pkt_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
-void ospf_tx_authenticate(struct ospf_iface *ifa, struct ospf_packet *pkt);
-void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt);
+void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
+unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
 int ospf_rx_hook(sock * sk, int size);
 void ospf_tx_hook(sock * sk);
 void ospf_err_hook(sock * sk, int err);
-void ospf_send_to_agt(sock * sk, u16 len, struct ospf_iface *ifa, u8 state);
-void ospf_send_to_bdr(sock * sk, u16 len, struct ospf_iface *ifa);
-void ospf_send_to(sock *sk, u16 len, ip_addr ip);
+void ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state);
+void ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa);
+void ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa);
 
 
 #endif /* _BIRD_OSPF_PACKET_H_ */
index 0360f8b6d7ada38b8ccc642fd2bae3c3399a4f1e..cee1589e2c65811cc7735260e1b2ad1ef915253b 100644 (file)
@@ -483,8 +483,7 @@ ospf_rt_sum(struct ospf_area *oa)
         continue;
       type = ORT_NET;
     }
-
-    if (en->lsa.type == LSA_T_SUM_RT)
+    else
     {
       ip = ipa_from_u32(en->lsa.id);
       mlen = 32;