summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/checksum.c53
-rw-r--r--ospfd/ospf_lsa.c7
-rw-r--r--ospfd/ospf_packet.c4
-rw-r--r--ospfd/ospf_route.h6
-rw-r--r--ospfd/ospf_vty.c137
-rw-r--r--ospfd/ospfd.c14
-rw-r--r--ospfd/ospfd.h3
7 files changed, 185 insertions, 39 deletions
diff --git a/lib/checksum.c b/lib/checksum.c
index 3ddde815..af4f2550 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -14,27 +14,20 @@ in_cksum(void *parg, int nbytes)
{
u_short *ptr = parg;
register long sum; /* assumes long == 32 bits */
- u_short oddbyte;
register u_short answer; /* assumes u_short == 16 bits */
-
+ register int count;
/*
* Our algorithm is simple, using a 32-bit accumulator (sum),
* we add sequential 16-bit words to it, and at the end, fold back
* all the carry bits from the top 16 bits into the lower 16 bits.
*/
-
sum = 0;
- while (nbytes > 1) {
- sum += *ptr++;
- nbytes -= 2;
- }
-
- /* mop up an odd byte, if necessary */
- if (nbytes == 1) {
- oddbyte = 0; /* make sure top half is zero */
- *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */
- sum += oddbyte;
- }
+ count = nbytes >> 1; /* div by 2 */
+ for(ptr--; count; --count)
+ sum += *++ptr;
+
+ if (nbytes & 1) /* Odd */
+ sum += *(u_char *)(++ptr); /* one byte only */
/*
* Add back carry outs from top 16 bits to low 16 bits.
@@ -56,11 +49,8 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
{
u_int8_t *p;
int x, y, c0, c1;
- u_int16_t checksum;
u_int16_t *csum;
size_t partial_len, i, left = len;
-
- checksum = 0;
assert (offset < len);
@@ -68,47 +58,42 @@ fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
* Zero the csum in the packet.
*/
csum = (u_int16_t *) (buffer + offset);
- *(csum) = 0;
+ *csum = 0;
- p = buffer;
+ p = buffer - 1;
c0 = 0;
c1 = 0;
while (left != 0)
{
partial_len = MIN(left, MODX);
+ left -= partial_len;
- for (i = 0; i < partial_len; i++)
+ do
{
- c0 = c0 + *(p++);
+ c0 = c0 + *(++p);
c1 += c0;
- }
+ } while (--partial_len);
c0 = c0 % 255;
c1 = c1 % 255;
-
- left -= partial_len;
}
-
+
/* The cast is important, to ensure the mod is taken as a signed value. */
x = (int)((len - offset - 1) * c0 - c1) % 255;
if (x <= 0)
x += 255;
y = 510 - c0 - x;
- if (y > 255)
+ if (y > 255)
y -= 255;
-
+
/*
* Now we write this to the packet.
* We could skip this step too, since the checksum returned would
* be stored into the checksum field by the caller.
+ * Checksum is always big endian.
*/
- buffer[offset] = x;
- buffer[offset + 1] = y;
-
- /* Take care of the endian issue */
- checksum = htons((x << 8) | (y & 0xFF));
-
- return checksum;
+ *csum = htons((x << 8) | (y & 0xFF));
+ return *csum;
}
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index 70504692..c9f2cba3 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -651,6 +651,8 @@ lsa_link_ptomp_set (struct stream *s, struct ospf_interface *oi)
static int
router_lsa_link_set (struct stream *s, struct ospf_area *area)
{
+ struct ospf_host_route *host;
+ struct in_addr host_mask = {~0}; /* All ones */
struct listnode *node;
struct ospf_interface *oi;
int links = 0;
@@ -688,7 +690,10 @@ router_lsa_link_set (struct stream *s, struct ospf_area *area)
}
}
}
-
+ for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host))
+ if (host->area == NULL || host->area == area)
+ links += link_info_set (s, host->host_addr, host_mask,
+ LSA_LINK_TYPE_STUB, 0, host->cost);
return links;
}
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index bc00def4..74e1d46f 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -324,7 +324,7 @@ static int
ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
{
struct ospf_header *ospfh;
- unsigned char digest[OSPF_AUTH_MD5_SIZE];
+ unsigned char digest[OSPF_AUTH_MD5_SIZE] = {0};
MD5_CTX ctx;
void *ibuf;
u_int32_t t;
@@ -351,7 +351,7 @@ ospf_make_md5_digest (struct ospf_interface *oi, struct ospf_packet *op)
/* Get MD5 Authentication key from auth_key list. */
if (list_isempty (OSPF_IF_PARAM (oi, auth_crypt)))
- auth_key = (const u_int8_t *) "";
+ auth_key = (const u_int8_t *) digest;
else
{
ck = listgetdata (listtail(OSPF_IF_PARAM (oi, auth_crypt)));
diff --git a/ospfd/ospf_route.h b/ospfd/ospf_route.h
index 17ab68e5..5483aaf5 100644
--- a/ospfd/ospf_route.h
+++ b/ospfd/ospf_route.h
@@ -121,6 +121,12 @@ struct ospf_route
} u;
};
+struct ospf_host_route {
+ struct in_addr host_addr;
+ u_int32_t cost; /* i.e. metric. */
+ struct ospf_area *area; /* NULL == all areas */
+};
+
extern struct ospf_path *ospf_path_new (void);
extern void ospf_path_free (struct ospf_path *);
extern struct ospf_path *ospf_path_lookup (struct list *, struct ospf_path *);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index a3c39447..be028228 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -7384,6 +7384,123 @@ DEFUN (show_ip_ospf_route,
return CMD_SUCCESS;
}
+DEFUN (ip_ospf_host,
+ ip_ospf_host_cmd,
+ "ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all) cost <0-65535>",
+ "OSPF specific commands\n"
+ "Add a host route to OPSF\n"
+ "Host route in IP address format\n")
+{
+ struct ospf *ospf;
+ u_int32_t cost;
+ struct ospf_area *area = NULL;
+ struct in_addr host_addr, area_id;
+ struct ospf_host_route *host = NULL;
+ struct listnode *node;
+ int ret, format;
+
+ ospf = ospf_lookup ();
+ if (ospf == NULL)
+ {
+ vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ ret = inet_aton (argv[0], &host_addr);
+ if (!ret)
+ {
+ vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ cost = strtol (argv[2], NULL, 10);
+ /* cost range is <0-65535>. */
+ if (cost < 0 || cost > 65535)
+ {
+ vty_out (vty, "cost is invalid%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (strcmp(argv[1], "all") != 0)
+ {
+ VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]); /* returns if error */
+ area = ospf_area_get (ospf, area_id, format);
+ }
+
+
+ for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host))
+ if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) &&
+ area == host->area)
+ break;
+
+ if (!node)
+ {
+ host = XCALLOC (MTYPE_OSPF_TOP, sizeof (struct ospf_host_route));
+ listnode_add (ospf->hostlist, host);
+ }
+ host->host_addr = host_addr;
+ host->cost = cost;
+ host->area = area;
+
+ if (!area)
+ for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
+ ospf_router_lsa_timer_add(area);
+ else
+ ospf_router_lsa_timer_add(area);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_ip_ospf_host,
+ no_ip_ospf_host_cmd,
+ "no ip ospf host A.B.C.D area (A.B.C.D|<0-4294967295>|all)",
+ NO_STR
+ "OSPF specific commands\n"
+ "Host route in IP address format\n")
+{
+ struct ospf *ospf;
+ struct ospf_area *area = NULL;
+ struct in_addr host_addr, area_id;
+ struct ospf_host_route *host = NULL;
+ struct listnode *node;
+ int ret, format;
+
+ ospf = ospf_lookup ();
+ if (ospf == NULL)
+ {
+ vty_out (vty, " OSPF Routing Process not enabled%s", VTY_NEWLINE);
+ return CMD_SUCCESS;
+ }
+ ret = inet_aton (argv[0], &host_addr);
+ if (!ret)
+ {
+ vty_out (vty, "Please specify host route by A.B.C.D%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (strcmp(argv[1], "all") != 0)
+ {
+ VTY_GET_OSPF_AREA_ID (area_id, format, argv[1]);
+ area = ospf_area_get (ospf, area_id, format);
+ }
+
+ for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host))
+ if (IPV4_ADDR_SAME (&host_addr, &host->host_addr) &&
+ area == host->area)
+ break;
+
+ if (node)
+ {
+ listnode_delete (ospf->hostlist, host);
+ XFREE (MTYPE_OSPF_TOP, host);
+ if (!area)
+ for (ALL_LIST_ELEMENTS_RO (ospf->areas, node, area))
+ ospf_router_lsa_timer_add(area);
+ else
+ ospf_router_lsa_timer_add(area);
+ }
+ return CMD_SUCCESS;
+}
+
const char *ospf_abr_type_str[] =
{
@@ -7965,6 +8082,7 @@ ospf_config_write (struct vty *vty)
struct interface *ifp;
struct ospf_interface *oi;
struct listnode *node;
+ struct ospf_host_route *host;
int write = 0;
ospf = ospf_lookup ();
@@ -8032,7 +8150,20 @@ ospf_config_write (struct vty *vty)
/* passive-interface print. */
if (ospf->passive_interface_default == OSPF_IF_PASSIVE)
vty_out (vty, " passive-interface default%s", VTY_NEWLINE);
-
+
+ for (ALL_LIST_ELEMENTS_RO (ospf->hostlist, node, host))
+ {
+ char buf[28];
+
+ if (host->area)
+ area_id2str(buf, sizeof(buf), host->area);
+ else
+ strcpy(buf, "all");
+ vty_out (vty, " ip ospf host %s area %s cost %d%s",
+ inet_ntoa (host->host_addr),
+ buf, host->cost, VTY_NEWLINE);
+ }
+
for (ALL_LIST_ELEMENTS_RO (om->iflist, node, ifp))
if (OSPF_IF_PARAM_CONFIGURED (IF_DEF_PARAMS (ifp), passive_interface)
&& IF_DEF_PARAMS (ifp)->passive_interface !=
@@ -8518,6 +8649,10 @@ ospf_vty_init (void)
install_element (OSPF_NODE, &no_ospf_neighbor_priority_cmd);
install_element (OSPF_NODE, &no_ospf_neighbor_poll_interval_cmd);
+ /* "ip ospf host" commands. */
+ install_element (OSPF_NODE, &ip_ospf_host_cmd);
+ install_element (OSPF_NODE, &no_ip_ospf_host_cmd);
+
/* Init interface related vty commands. */
ospf_vty_if_init ();
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 1f32a484..11d1b9d1 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -231,7 +231,7 @@ ospf_new (void)
}
new->t_read = thread_add_read (master, ospf_read, new, new->fd);
new->oi_write_q = list_new ();
-
+ new->hostlist = list_new(); /* host route list */
return new;
}
@@ -401,6 +401,7 @@ ospf_finish_final (struct ospf *ospf)
struct ospf_lsa *lsa;
struct ospf_interface *oi;
struct ospf_area *area;
+ struct ospf_host_route *host;
struct ospf_vl_data *vl_data;
struct listnode *node, *nnode;
int i;
@@ -471,6 +472,12 @@ ospf_finish_final (struct ospf *ospf)
ospf_area_free (area);
}
+ for (ALL_LIST_ELEMENTS (ospf->hostlist, node, nnode, host))
+ {
+ listnode_delete (ospf->hostlist, host);
+ XFREE (MTYPE_OSPF_TOP, host);
+ }
+
/* Cancel all timers. */
OSPF_TIMER_OFF (ospf->t_external_lsa);
OSPF_TIMER_OFF (ospf->t_router_lsa_update);
@@ -646,6 +653,8 @@ ospf_area_free (struct ospf_area *area)
void
ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
{
+ struct ospf_host_route *host;
+ struct listnode *node;
struct ospf_area *area;
area = ospf_area_lookup_by_area_id (ospf, area_id);
@@ -660,6 +669,9 @@ ospf_area_check_free (struct ospf *ospf, struct in_addr area_id)
IMPORT_NAME (area) == NULL &&
area->auth_type == OSPF_AUTH_NULL)
{
+ for (ALL_LIST_ELEMENTS_RO (area->ospf->hostlist, node, host))
+ if (!host->area || host->area == area)
+ return;
listnode_delete (ospf->areas, area);
ospf_area_free (area);
}
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index b24b3ced..6ced9c72 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -327,6 +327,9 @@ struct ospf
u_int32_t rx_lsa_count;
struct route_table *distance_table;
+
+ /* Host route list */
+ struct list *hostlist;
};
/* OSPF area structure. */