Annotation of embedaddon/quagga/ripngd/ripng_offset.c, revision 1.1
1.1 ! misho 1: /* RIPng offset-list
! 2: * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
! 3: *
! 4: * This file is part of GNU Zebra.
! 5: *
! 6: * GNU Zebra is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2, or (at your option) any
! 9: * later version.
! 10: *
! 11: * GNU Zebra is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: * 02111-1307, USA.
! 20: */
! 21:
! 22: /* RIPng support by Vincent Jardin <vincent.jardin@6wind.com>
! 23: * Copyright (C) 2002 6WIND
! 24: */
! 25:
! 26: #include <zebra.h>
! 27:
! 28: #include "if.h"
! 29: #include "prefix.h"
! 30: #include "filter.h"
! 31: #include "command.h"
! 32: #include "linklist.h"
! 33: #include "memory.h"
! 34:
! 35: #include "ripngd/ripngd.h"
! 36:
! 37: #define RIPNG_OFFSET_LIST_IN 0
! 38: #define RIPNG_OFFSET_LIST_OUT 1
! 39: #define RIPNG_OFFSET_LIST_MAX 2
! 40:
! 41: struct ripng_offset_list
! 42: {
! 43: char *ifname;
! 44:
! 45: struct
! 46: {
! 47: char *alist_name;
! 48: /* struct access_list *alist; */
! 49: int metric;
! 50: } direct[RIPNG_OFFSET_LIST_MAX];
! 51: };
! 52:
! 53: static struct list *ripng_offset_list_master;
! 54:
! 55: static int
! 56: strcmp_safe (const char *s1, const char *s2)
! 57: {
! 58: if (s1 == NULL && s2 == NULL)
! 59: return 0;
! 60: if (s1 == NULL)
! 61: return -1;
! 62: if (s2 == NULL)
! 63: return 1;
! 64: return strcmp (s1, s2);
! 65: }
! 66:
! 67: static struct ripng_offset_list *
! 68: ripng_offset_list_new ()
! 69: {
! 70: struct ripng_offset_list *new;
! 71:
! 72: new = XCALLOC (MTYPE_RIPNG_OFFSET_LIST, sizeof (struct ripng_offset_list));
! 73: return new;
! 74: }
! 75:
! 76: static void
! 77: ripng_offset_list_free (struct ripng_offset_list *offset)
! 78: {
! 79: XFREE (MTYPE_RIPNG_OFFSET_LIST, offset);
! 80: }
! 81:
! 82: static struct ripng_offset_list *
! 83: ripng_offset_list_lookup (const char *ifname)
! 84: {
! 85: struct ripng_offset_list *offset;
! 86: struct listnode *node, *nnode;
! 87:
! 88: for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset))
! 89: {
! 90: if (strcmp_safe (offset->ifname, ifname) == 0)
! 91: return offset;
! 92: }
! 93: return NULL;
! 94: }
! 95:
! 96: static struct ripng_offset_list *
! 97: ripng_offset_list_get (const char *ifname)
! 98: {
! 99: struct ripng_offset_list *offset;
! 100:
! 101: offset = ripng_offset_list_lookup (ifname);
! 102: if (offset)
! 103: return offset;
! 104:
! 105: offset = ripng_offset_list_new ();
! 106: if (ifname)
! 107: offset->ifname = strdup (ifname);
! 108: listnode_add_sort (ripng_offset_list_master, offset);
! 109:
! 110: return offset;
! 111: }
! 112:
! 113: static int
! 114: ripng_offset_list_set (struct vty *vty, const char *alist,
! 115: const char *direct_str, const char *metric_str,
! 116: const char *ifname)
! 117: {
! 118: int direct;
! 119: int metric;
! 120: struct ripng_offset_list *offset;
! 121:
! 122: /* Check direction. */
! 123: if (strncmp (direct_str, "i", 1) == 0)
! 124: direct = RIPNG_OFFSET_LIST_IN;
! 125: else if (strncmp (direct_str, "o", 1) == 0)
! 126: direct = RIPNG_OFFSET_LIST_OUT;
! 127: else
! 128: {
! 129: vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
! 130: return CMD_WARNING;
! 131: }
! 132:
! 133: /* Check metric. */
! 134: metric = atoi (metric_str);
! 135: if (metric < 0 || metric > 16)
! 136: {
! 137: vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
! 138: return CMD_WARNING;
! 139: }
! 140:
! 141: /* Get offset-list structure with interface name. */
! 142: offset = ripng_offset_list_get (ifname);
! 143:
! 144: if (offset->direct[direct].alist_name)
! 145: free (offset->direct[direct].alist_name);
! 146: offset->direct[direct].alist_name = strdup (alist);
! 147: offset->direct[direct].metric = metric;
! 148:
! 149: return CMD_SUCCESS;
! 150: }
! 151:
! 152: static int
! 153: ripng_offset_list_unset (struct vty *vty, const char *alist,
! 154: const char *direct_str, const char *metric_str,
! 155: const char *ifname)
! 156: {
! 157: int direct;
! 158: int metric;
! 159: struct ripng_offset_list *offset;
! 160:
! 161: /* Check direction. */
! 162: if (strncmp (direct_str, "i", 1) == 0)
! 163: direct = RIPNG_OFFSET_LIST_IN;
! 164: else if (strncmp (direct_str, "o", 1) == 0)
! 165: direct = RIPNG_OFFSET_LIST_OUT;
! 166: else
! 167: {
! 168: vty_out (vty, "Invalid direction: %s%s", direct_str, VTY_NEWLINE);
! 169: return CMD_WARNING;
! 170: }
! 171:
! 172: /* Check metric. */
! 173: metric = atoi (metric_str);
! 174: if (metric < 0 || metric > 16)
! 175: {
! 176: vty_out (vty, "Invalid metric: %s%s", metric_str, VTY_NEWLINE);
! 177: return CMD_WARNING;
! 178: }
! 179:
! 180: /* Get offset-list structure with interface name. */
! 181: offset = ripng_offset_list_lookup (ifname);
! 182:
! 183: if (offset)
! 184: {
! 185: if (offset->direct[direct].alist_name)
! 186: free (offset->direct[direct].alist_name);
! 187: offset->direct[direct].alist_name = NULL;
! 188:
! 189: if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL &&
! 190: offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
! 191: {
! 192: listnode_delete (ripng_offset_list_master, offset);
! 193: if (offset->ifname)
! 194: free (offset->ifname);
! 195: ripng_offset_list_free (offset);
! 196: }
! 197: }
! 198: else
! 199: {
! 200: vty_out (vty, "Can't find offset-list%s", VTY_NEWLINE);
! 201: return CMD_WARNING;
! 202: }
! 203: return CMD_SUCCESS;
! 204: }
! 205:
! 206: #define OFFSET_LIST_IN_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
! 207: #define OFFSET_LIST_IN_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
! 208:
! 209: #define OFFSET_LIST_OUT_NAME(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
! 210: #define OFFSET_LIST_OUT_METRIC(O) ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
! 211:
! 212: /* If metric is modifed return 1. */
! 213: int
! 214: ripng_offset_list_apply_in (struct prefix_ipv6 *p, struct interface *ifp,
! 215: u_char *metric)
! 216: {
! 217: struct ripng_offset_list *offset;
! 218: struct access_list *alist;
! 219:
! 220: /* Look up offset-list with interface name. */
! 221: offset = ripng_offset_list_lookup (ifp->name);
! 222: if (offset && OFFSET_LIST_IN_NAME (offset))
! 223: {
! 224: alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
! 225:
! 226: if (alist
! 227: && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
! 228: {
! 229: *metric += OFFSET_LIST_IN_METRIC (offset);
! 230: return 1;
! 231: }
! 232: return 0;
! 233: }
! 234: /* Look up offset-list without interface name. */
! 235: offset = ripng_offset_list_lookup (NULL);
! 236: if (offset && OFFSET_LIST_IN_NAME (offset))
! 237: {
! 238: alist = access_list_lookup (AFI_IP6, OFFSET_LIST_IN_NAME (offset));
! 239:
! 240: if (alist
! 241: && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
! 242: {
! 243: *metric += OFFSET_LIST_IN_METRIC (offset);
! 244: return 1;
! 245: }
! 246: return 0;
! 247: }
! 248: return 0;
! 249: }
! 250:
! 251: /* If metric is modifed return 1. */
! 252: int
! 253: ripng_offset_list_apply_out (struct prefix_ipv6 *p, struct interface *ifp,
! 254: u_char *metric)
! 255: {
! 256: struct ripng_offset_list *offset;
! 257: struct access_list *alist;
! 258:
! 259: /* Look up offset-list with interface name. */
! 260: offset = ripng_offset_list_lookup (ifp->name);
! 261: if (offset && OFFSET_LIST_OUT_NAME (offset))
! 262: {
! 263: alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
! 264:
! 265: if (alist
! 266: && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
! 267: {
! 268: *metric += OFFSET_LIST_OUT_METRIC (offset);
! 269: return 1;
! 270: }
! 271: return 0;
! 272: }
! 273:
! 274: /* Look up offset-list without interface name. */
! 275: offset = ripng_offset_list_lookup (NULL);
! 276: if (offset && OFFSET_LIST_OUT_NAME (offset))
! 277: {
! 278: alist = access_list_lookup (AFI_IP6, OFFSET_LIST_OUT_NAME (offset));
! 279:
! 280: if (alist
! 281: && access_list_apply (alist, (struct prefix *)p) == FILTER_PERMIT)
! 282: {
! 283: *metric += OFFSET_LIST_OUT_METRIC (offset);
! 284: return 1;
! 285: }
! 286: return 0;
! 287: }
! 288: return 0;
! 289: }
! 290:
! 291: DEFUN (ripng_offset_list,
! 292: ripng_offset_list_cmd,
! 293: "offset-list WORD (in|out) <0-16>",
! 294: "Modify RIPng metric\n"
! 295: "Access-list name\n"
! 296: "For incoming updates\n"
! 297: "For outgoing updates\n"
! 298: "Metric value\n")
! 299: {
! 300: return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], NULL);
! 301: }
! 302:
! 303: DEFUN (ripng_offset_list_ifname,
! 304: ripng_offset_list_ifname_cmd,
! 305: "offset-list WORD (in|out) <0-16> IFNAME",
! 306: "Modify RIPng metric\n"
! 307: "Access-list name\n"
! 308: "For incoming updates\n"
! 309: "For outgoing updates\n"
! 310: "Metric value\n"
! 311: "Interface to match\n")
! 312: {
! 313: return ripng_offset_list_set (vty, argv[0], argv[1], argv[2], argv[3]);
! 314: }
! 315:
! 316: DEFUN (no_ripng_offset_list,
! 317: no_ripng_offset_list_cmd,
! 318: "no offset-list WORD (in|out) <0-16>",
! 319: NO_STR
! 320: "Modify RIPng metric\n"
! 321: "Access-list name\n"
! 322: "For incoming updates\n"
! 323: "For outgoing updates\n"
! 324: "Metric value\n")
! 325: {
! 326: return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], NULL);
! 327: }
! 328:
! 329: DEFUN (no_ripng_offset_list_ifname,
! 330: no_ripng_offset_list_ifname_cmd,
! 331: "no offset-list WORD (in|out) <0-16> IFNAME",
! 332: NO_STR
! 333: "Modify RIPng metric\n"
! 334: "Access-list name\n"
! 335: "For incoming updates\n"
! 336: "For outgoing updates\n"
! 337: "Metric value\n"
! 338: "Interface to match\n")
! 339: {
! 340: return ripng_offset_list_unset (vty, argv[0], argv[1], argv[2], argv[3]);
! 341: }
! 342:
! 343: static int
! 344: offset_list_cmp (struct ripng_offset_list *o1, struct ripng_offset_list *o2)
! 345: {
! 346: return strcmp_safe (o1->ifname, o2->ifname);
! 347: }
! 348:
! 349: static void
! 350: offset_list_del (struct ripng_offset_list *offset)
! 351: {
! 352: if (OFFSET_LIST_IN_NAME (offset))
! 353: free (OFFSET_LIST_IN_NAME (offset));
! 354: if (OFFSET_LIST_OUT_NAME (offset))
! 355: free (OFFSET_LIST_OUT_NAME (offset));
! 356: if (offset->ifname)
! 357: free (offset->ifname);
! 358: ripng_offset_list_free (offset);
! 359: }
! 360:
! 361: void
! 362: ripng_offset_init (void)
! 363: {
! 364: ripng_offset_list_master = list_new ();
! 365: ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
! 366: ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
! 367:
! 368: install_element (RIPNG_NODE, &ripng_offset_list_cmd);
! 369: install_element (RIPNG_NODE, &ripng_offset_list_ifname_cmd);
! 370: install_element (RIPNG_NODE, &no_ripng_offset_list_cmd);
! 371: install_element (RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
! 372: }
! 373:
! 374: void
! 375: ripng_offset_clean (void)
! 376: {
! 377: list_delete (ripng_offset_list_master);
! 378:
! 379: ripng_offset_list_master = list_new ();
! 380: ripng_offset_list_master->cmp = (int (*)(void *, void *)) offset_list_cmp;
! 381: ripng_offset_list_master->del = (void (*)(void *)) offset_list_del;
! 382: }
! 383:
! 384: int
! 385: config_write_ripng_offset_list (struct vty *vty)
! 386: {
! 387: struct listnode *node, *nnode;
! 388: struct ripng_offset_list *offset;
! 389:
! 390: for (ALL_LIST_ELEMENTS (ripng_offset_list_master, node, nnode, offset))
! 391: {
! 392: if (! offset->ifname)
! 393: {
! 394: if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
! 395: vty_out (vty, " offset-list %s in %d%s",
! 396: offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
! 397: offset->direct[RIPNG_OFFSET_LIST_IN].metric,
! 398: VTY_NEWLINE);
! 399: if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
! 400: vty_out (vty, " offset-list %s out %d%s",
! 401: offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
! 402: offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
! 403: VTY_NEWLINE);
! 404: }
! 405: else
! 406: {
! 407: if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
! 408: vty_out (vty, " offset-list %s in %d %s%s",
! 409: offset->direct[RIPNG_OFFSET_LIST_IN].alist_name,
! 410: offset->direct[RIPNG_OFFSET_LIST_IN].metric,
! 411: offset->ifname, VTY_NEWLINE);
! 412: if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
! 413: vty_out (vty, " offset-list %s out %d %s%s",
! 414: offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name,
! 415: offset->direct[RIPNG_OFFSET_LIST_OUT].metric,
! 416: offset->ifname, VTY_NEWLINE);
! 417: }
! 418: }
! 419:
! 420: return 0;
! 421: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>