diff options
-rw-r--r-- | lib/checksum.c | 53 | ||||
-rw-r--r-- | ospfd/ospf_lsa.c | 7 | ||||
-rw-r--r-- | ospfd/ospf_packet.c | 4 | ||||
-rw-r--r-- | ospfd/ospf_route.h | 6 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 137 | ||||
-rw-r--r-- | ospfd/ospfd.c | 14 | ||||
-rw-r--r-- | ospfd/ospfd.h | 3 |
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. */ |