Annotation of embedaddon/mpd/src/iface.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * iface.c
! 4: *
! 5: * Written by Archie Cobbs <archie@freebsd.org>
! 6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
! 7: * See ``COPYRIGHT.whistle''
! 8: *
! 9: * TCP MSSFIX code copyright (c) 2000 Ruslan Ermilov
! 10: * TCP MSSFIX contributed by Sergey Korolew <dsATbittu.org.ru>
! 11: *
! 12: */
! 13:
! 14: #include "ppp.h"
! 15: #include "iface.h"
! 16: #include "ipcp.h"
! 17: #include "auth.h"
! 18: #include "ngfunc.h"
! 19: #include "netgraph.h"
! 20: #include "util.h"
! 21:
! 22: #include <sys/sockio.h>
! 23: #include <sys/sysctl.h>
! 24: #include <net/if.h>
! 25: #include <net/if_types.h>
! 26: #include <net/if_dl.h>
! 27: #include <net/if_var.h>
! 28: #include <net/route.h>
! 29: #include <netinet/in_systm.h>
! 30: #include <netinet/in.h>
! 31: #include <netinet/in_var.h>
! 32: #include <netinet/if_ether.h>
! 33: #include <netinet6/nd6.h>
! 34: #include <netgraph/ng_message.h>
! 35: #include <netgraph/ng_iface.h>
! 36: #ifdef USE_NG_BPF
! 37: #include <netgraph/ng_bpf.h>
! 38: #endif
! 39: #include <netgraph/ng_tee.h>
! 40: #include <netgraph/ng_ksocket.h>
! 41: #include <netinet/ip_icmp.h>
! 42: #include <netinet/tcp.h>
! 43: #include <netinet/udp.h>
! 44: #ifdef USE_NG_TCPMSS
! 45: #include <netgraph/ng_tcpmss.h>
! 46: #endif
! 47: #ifdef USE_NG_IPACCT
! 48: #include <netgraph/ng_ipacct.h>
! 49: #undef r_ip_p /* XXX:DIRTY CONFLICT! */
! 50: #endif
! 51: #ifdef USE_NG_NETFLOW
! 52: #include <netgraph/netflow/ng_netflow.h>
! 53: #endif
! 54: #ifdef USE_NG_CAR
! 55: #include <netgraph/ng_car.h>
! 56: #endif
! 57:
! 58: #ifdef USE_NG_BPF
! 59: #include <pcap.h>
! 60: #endif
! 61:
! 62: /*
! 63: * DEFINITIONS
! 64: */
! 65:
! 66: /* Set menu options */
! 67:
! 68: enum {
! 69: SET_IDLE,
! 70: SET_SESSION,
! 71: SET_ADDRS,
! 72: SET_ROUTE,
! 73: SET_MTU,
! 74: SET_NAME,
! 75: #ifdef SIOCSIFDESCR
! 76: SET_DESCR,
! 77: #endif
! 78: #ifdef SIOCAIFGROUP
! 79: SET_GROUP,
! 80: #endif
! 81: SET_UP_SCRIPT,
! 82: SET_DOWN_SCRIPT,
! 83: SET_ENABLE,
! 84: SET_DISABLE
! 85: };
! 86:
! 87: /*
! 88: * INTERNAL FUNCTIONS
! 89: */
! 90:
! 91: static int IfaceNgIpInit(Bund b, int ready);
! 92: static void IfaceNgIpShutdown(Bund b);
! 93: static int IfaceNgIpv6Init(Bund b, int ready);
! 94: static void IfaceNgIpv6Shutdown(Bund b);
! 95:
! 96: #ifdef USE_NG_NETFLOW
! 97: static int IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out);
! 98: static int IfaceSetupNetflow(Bund b, char in, char out);
! 99: static void IfaceShutdownNetflow(Bund b, char in, char out);
! 100: #endif
! 101:
! 102: #ifdef USE_NG_IPACCT
! 103: static int IfaceInitIpacct(Bund b, char *path, char *hook);
! 104: static void IfaceShutdownIpacct(Bund b);
! 105: #endif
! 106:
! 107: #ifdef USE_NG_NAT
! 108: static int IfaceInitNAT(Bund b, char *path, char *hook);
! 109: static int IfaceSetupNAT(Bund b);
! 110: static void IfaceShutdownNAT(Bund b);
! 111: #endif
! 112:
! 113: static int IfaceInitTee(Bund b, char *path, char *hook, int v6);
! 114: static void IfaceShutdownTee(Bund b, int v6);
! 115:
! 116: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 117: static int IfaceInitMSS(Bund b, char *path, char *hook);
! 118: static void IfaceSetupMSS(Bund b, uint16_t maxMSS);
! 119: static void IfaceShutdownMSS(Bund b);
! 120: #endif
! 121:
! 122: #ifdef USE_NG_BPF
! 123: static int IfaceInitLimits(Bund b, char *path, char *hook);
! 124: static void IfaceSetupLimits(Bund b);
! 125: static void IfaceShutdownLimits(Bund b);
! 126: #endif
! 127:
! 128: static int IfaceSetCommand(Context ctx, int ac, char *av[], void *arg);
! 129: static void IfaceSessionTimeout(void *arg);
! 130: static void IfaceIdleTimeout(void *arg);
! 131:
! 132: static void IfaceCacheSend(Bund b);
! 133: static void IfaceCachePkt(Bund b, int proto, Mbuf pkt);
! 134: static int IfaceIsDemand(int proto, Mbuf pkt);
! 135:
! 136: #ifdef USE_IPFW
! 137: static int IfaceAllocACL (struct acl_pool ***ap, int start, char * ifname, int number);
! 138: static int IfaceFindACL (struct acl_pool *ap, char * ifname, int number);
! 139: static char * IFaceParseACL (char * src, char * ifname);
! 140: #endif
! 141:
! 142: static int IfaceSetName(Bund b, const char * ifname);
! 143: #ifdef SIOCSIFDESCR
! 144: static int IfaceSetDescr(Bund b, const char * ifdescr);
! 145: #endif
! 146: #ifdef SIOCAIFGROUP
! 147: static int IfaceAddGroup(Bund b, const char * ifgroup);
! 148: static int IfaceDelGroup(Bund b, const char * ifgroup);
! 149: #endif
! 150: /*
! 151: * GLOBAL VARIABLES
! 152: */
! 153:
! 154: const struct cmdtab IfaceSetCmds[] = {
! 155: { "addrs {self} {peer}", "Set interface addresses",
! 156: IfaceSetCommand, NULL, 2, (void *) SET_ADDRS },
! 157: { "route {dest}[/{width}]", "Add IP route",
! 158: IfaceSetCommand, NULL, 2, (void *) SET_ROUTE },
! 159: { "mtu {size}", "Set max allowed interface MTU",
! 160: IfaceSetCommand, NULL, 2, (void *) SET_MTU },
! 161: { "name [{name}]", "Set interface name",
! 162: IfaceSetCommand, NULL, 2, (void *) SET_NAME },
! 163: #ifdef SIOCSIFDESCR
! 164: { "description [{descr}]", "Set interface description",
! 165: IfaceSetCommand, NULL, 2, (void *) SET_DESCR },
! 166: #endif
! 167: #ifdef SIOCAIFGROUP
! 168: { "group [{group}]", "Set interface group",
! 169: IfaceSetCommand, NULL, 2, (void *) SET_GROUP },
! 170: #endif
! 171: { "up-script [{progname}]", "Interface up script",
! 172: IfaceSetCommand, NULL, 2, (void *) SET_UP_SCRIPT },
! 173: { "down-script [{progname}]", "Interface down script",
! 174: IfaceSetCommand, NULL, 2, (void *) SET_DOWN_SCRIPT },
! 175: #ifdef USE_NG_BPF
! 176: { "idle {seconds}", "Idle timeout",
! 177: IfaceSetCommand, NULL, 2, (void *) SET_IDLE },
! 178: #endif
! 179: { "session {seconds}", "Session timeout",
! 180: IfaceSetCommand, NULL, 2, (void *) SET_SESSION },
! 181: { "enable [opt ...]", "Enable option",
! 182: IfaceSetCommand, NULL, 2, (void *) SET_ENABLE },
! 183: { "disable [opt ...]", "Disable option",
! 184: IfaceSetCommand, NULL, 2, (void *) SET_DISABLE },
! 185: { NULL },
! 186: };
! 187:
! 188: /*
! 189: * INTERNAL VARIABLES
! 190: */
! 191:
! 192: static const struct confinfo gConfList[] = {
! 193: { 0, IFACE_CONF_ONDEMAND, "on-demand" },
! 194: { 0, IFACE_CONF_PROXY, "proxy-arp" },
! 195: #ifdef USE_NG_TCPMSS
! 196: { 0, IFACE_CONF_TCPMSSFIX, "tcpmssfix" },
! 197: #endif
! 198: { 0, IFACE_CONF_TEE, "tee" },
! 199: #ifdef USE_NG_NAT
! 200: { 0, IFACE_CONF_NAT, "nat" },
! 201: #endif
! 202: #ifdef USE_NG_NETFLOW
! 203: { 0, IFACE_CONF_NETFLOW_IN, "netflow-in" },
! 204: { 0, IFACE_CONF_NETFLOW_OUT, "netflow-out" },
! 205: #ifdef NG_NETFLOW_CONF_ONCE
! 206: { 0, IFACE_CONF_NETFLOW_ONCE, "netflow-once" },
! 207: #endif
! 208: #endif
! 209: #ifdef USE_NG_IPACCT
! 210: { 0, IFACE_CONF_IPACCT, "ipacct" },
! 211: #endif
! 212: { 0, 0, NULL },
! 213: };
! 214:
! 215: #ifdef USE_IPFW
! 216: struct acl_pool * rule_pool = NULL; /* Pointer to the first element in the list of rules */
! 217: struct acl_pool * pipe_pool = NULL; /* Pointer to the first element in the list of pipes */
! 218: struct acl_pool * queue_pool = NULL; /* Pointer to the first element in the list of queues */
! 219: struct acl_pool * table_pool = NULL; /* Pointer to the first element in the list of tables */
! 220: int rule_pool_start = 10000; /* Initial number of ipfw rules pool */
! 221: int pipe_pool_start = 10000; /* Initial number of ipfw dummynet pipe pool */
! 222: int queue_pool_start = 10000; /* Initial number of ipfw dummynet queue pool */
! 223: int table_pool_start = 32; /* Initial number of ipfw tables pool */
! 224: #endif
! 225:
! 226: #ifdef USE_NG_BPF
! 227: /* A BPF filter that matches TCP SYN packets */
! 228: static const struct bpf_insn gTCPSYNProg[] = {
! 229: /*00*/ BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 9), /* A <- IP protocol */
! 230: /*01*/ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, 6), /* !TCP => 8 */
! 231: /*02*/ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 6), /* A <- fragmentation offset */
! 232: /*03*/ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, 0x1fff, 4, 0), /* fragment => 8 */
! 233: /*04*/ BPF_STMT(BPF_LDX+BPF_B+BPF_MSH, 0), /* X <- header len */
! 234: /*05*/ BPF_STMT(BPF_LD+BPF_B+BPF_IND, 13), /* A <- TCP flags */
! 235: /*06*/ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, TH_SYN, 0, 1), /* !TH_SYN => 8 */
! 236: /*07*/ BPF_STMT(BPF_RET+BPF_K, (u_int)-1), /* accept packet */
! 237: /*08*/ BPF_STMT(BPF_RET+BPF_K, 0), /* reject packet */
! 238: };
! 239:
! 240: #define TCPSYN_PROG_LEN (sizeof(gTCPSYNProg) / sizeof(*gTCPSYNProg))
! 241:
! 242: /* A BPF filter that matches nothing */
! 243: static const struct bpf_insn gNoMatchProg[] = {
! 244: BPF_STMT(BPF_RET+BPF_K, 0)
! 245: };
! 246:
! 247: #define NOMATCH_PROG_LEN (sizeof(gNoMatchProg) / sizeof(*gNoMatchProg))
! 248:
! 249: /* A BPF filter that matches everything */
! 250: static const struct bpf_insn gMatchProg[] = {
! 251: BPF_STMT(BPF_RET+BPF_K, (u_int)-1)
! 252: };
! 253:
! 254: #define MATCH_PROG_LEN (sizeof(gMatchProg) / sizeof(*gMatchProg))
! 255: #endif /* USE_NG_BPF */
! 256:
! 257: #define IN6MASK128 {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
! 258: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
! 259: static const struct in6_addr in6mask128 = IN6MASK128;
! 260:
! 261:
! 262: /*
! 263: * IfaceInit()
! 264: */
! 265:
! 266: void
! 267: IfaceInit(Bund b)
! 268: {
! 269: IfaceState const iface = &b->iface;
! 270:
! 271: /* Default configuration */
! 272: iface->mtu = NG_IFACE_MTU_DEFAULT;
! 273: iface->max_mtu = NG_IFACE_MTU_DEFAULT;
! 274: #ifdef SIOCSIFDESCR
! 275: iface->ifdescr = NULL;
! 276: iface->conf.ifdescr = NULL;
! 277: #endif
! 278: Disable(&iface->options, IFACE_CONF_ONDEMAND);
! 279: Disable(&iface->options, IFACE_CONF_PROXY);
! 280: Disable(&iface->options, IFACE_CONF_TCPMSSFIX);
! 281: #ifdef USE_NG_NAT
! 282: NatInit(b);
! 283: #endif
! 284: #ifdef USE_NG_BPF
! 285: SLIST_INIT(&iface->ss[0]);
! 286: SLIST_INIT(&iface->ss[1]);
! 287: #endif
! 288: }
! 289:
! 290: /*
! 291: * IfaceInst()
! 292: */
! 293:
! 294: void
! 295: IfaceInst(Bund b, Bund bt)
! 296: {
! 297: IfaceState const iface = &b->iface;
! 298:
! 299: memcpy(iface, &bt->iface, sizeof(*iface));
! 300:
! 301: /* Copy interface name from template config to current */
! 302: if (bt->iface.conf.ifname[0] != 0 && b->tmpl == 0) {
! 303: snprintf(iface->conf.ifname, sizeof(iface->conf.ifname), "%s%d",
! 304: bt->iface.conf.ifname, b->id);
! 305: Log(LG_IFACE2, ("[%s] IFACE: Set conf.ifname to ", iface->conf.ifname));
! 306: }
! 307: }
! 308:
! 309: /*
! 310: * IfaceDestroy()
! 311: */
! 312:
! 313: void
! 314: IfaceDestroy(Bund b)
! 315: {
! 316: #ifdef SIOCSIFDESCR
! 317: IfaceState const iface = &b->iface;
! 318:
! 319: if (iface->conf.ifdescr != NULL)
! 320: Freee(iface->conf.ifdescr);
! 321: #endif
! 322: }
! 323:
! 324: /*
! 325: * IfaceOpen()
! 326: *
! 327: * Open the interface layer
! 328: */
! 329:
! 330: void
! 331: IfaceOpen(Bund b)
! 332: {
! 333: IfaceState const iface = &b->iface;
! 334:
! 335: Log(LG_IFACE, ("[%s] IFACE: Open event", b->name));
! 336:
! 337: /* Open is useless without on-demand. */
! 338: if (!Enabled(&iface->options, IFACE_CONF_ONDEMAND)) {
! 339: Log(LG_ERR, ("[%s] 'open iface' is useless without on-demand enabled", b->name));
! 340: return;
! 341: }
! 342:
! 343: /* If interface is already open do nothing */
! 344: if (iface->open)
! 345: return;
! 346: iface->open = TRUE;
! 347:
! 348: /* If on-demand, bring up system interface immediately and start
! 349: listening for outgoing packets. The next outgoing packet will
! 350: cause us to open the lower layer(s) */
! 351: BundNcpsJoin(b, NCP_NONE);
! 352: }
! 353:
! 354: /*
! 355: * IfaceClose()
! 356: *
! 357: * Close the interface layer
! 358: */
! 359:
! 360: void
! 361: IfaceClose(Bund b)
! 362: {
! 363: IfaceState const iface = &b->iface;
! 364:
! 365: Log(LG_IFACE, ("[%s] IFACE: Close event", b->name));
! 366:
! 367: /* If interface is already closed do nothing */
! 368: if (!iface->open)
! 369: return;
! 370: iface->open = FALSE;
! 371:
! 372: /* If there was on-demand, tell that it is not needed anymore */
! 373: BundNcpsLeave(b, NCP_NONE);
! 374: }
! 375:
! 376: /*
! 377: * IfaceOpenCmd()
! 378: *
! 379: * Open the interface layer
! 380: */
! 381:
! 382: int
! 383: IfaceOpenCmd(Context ctx)
! 384: {
! 385: if (ctx->bund->tmpl)
! 386: Error("impossible to open template");
! 387: IfaceOpen(ctx->bund);
! 388: return (0);
! 389: }
! 390:
! 391: /*
! 392: * IfaceCloseCmd()
! 393: *
! 394: * Close the interface layer
! 395: */
! 396:
! 397: int
! 398: IfaceCloseCmd(Context ctx)
! 399: {
! 400: if (ctx->bund->tmpl)
! 401: Error("impossible to close template");
! 402: IfaceClose(ctx->bund);
! 403: return (0);
! 404: }
! 405:
! 406: /*
! 407: * IfaceUp()
! 408: *
! 409: * Our underlying PPP bundle is ready for traffic.
! 410: * We may signal that the interface is in DoD with the IFF_LINK0 flag.
! 411: */
! 412:
! 413: void
! 414: IfaceUp(Bund b, int ready)
! 415: {
! 416: IfaceState const iface = &b->iface;
! 417: int session_timeout = 0, idle_timeout = 0;
! 418: #ifdef USE_IPFW
! 419: struct acl *acls, *acl;
! 420: char *buf;
! 421: struct acl_pool **poollast;
! 422: int poollaststart;
! 423: int prev_number;
! 424: int prev_real_number;
! 425: #endif
! 426:
! 427: Log(LG_IFACE, ("[%s] IFACE: Up event", b->name));
! 428: iface->last_up = time(NULL);
! 429:
! 430: if (ready) {
! 431:
! 432: /* Start Session timer */
! 433: if (b->params.session_timeout > 0) {
! 434: session_timeout = b->params.session_timeout;
! 435: } else if (iface->session_timeout > 0) {
! 436: session_timeout = iface->session_timeout;
! 437: }
! 438:
! 439: if (session_timeout > 0) {
! 440: Log(LG_IFACE2, ("[%s] IFACE: session-timeout: %d seconds",
! 441: b->name, session_timeout));
! 442: if (session_timeout > INT_MAX / 1100) {
! 443: session_timeout = INT_MAX / 1100;
! 444: Log(LG_ERR, ("[%s] IFACE: session-timeout limited to %d seconds",
! 445: b->name, session_timeout));
! 446: }
! 447: TimerInit(&iface->sessionTimer, "IfaceSession",
! 448: session_timeout * SECONDS, IfaceSessionTimeout, b);
! 449: TimerStart(&iface->sessionTimer);
! 450: }
! 451:
! 452: /* Start idle timer */
! 453: if (b->params.idle_timeout > 0) {
! 454: idle_timeout = b->params.idle_timeout;
! 455: } else if (iface->idle_timeout > 0) {
! 456: idle_timeout = iface->idle_timeout;
! 457: }
! 458:
! 459: if (idle_timeout > 0) {
! 460: Log(LG_IFACE2, ("[%s] IFACE: idle-timeout: %d seconds",
! 461: b->name, idle_timeout));
! 462: if (idle_timeout > INT_MAX / 1100 * IFACE_IDLE_SPLIT) {
! 463: idle_timeout = INT_MAX / 1100 * IFACE_IDLE_SPLIT;
! 464: Log(LG_ERR, ("[%s] IFACE: idle-timeout limited to %d seconds",
! 465: b->name, idle_timeout));
! 466: }
! 467: TimerInit(&iface->idleTimer, "IfaceIdle",
! 468: idle_timeout * SECONDS / IFACE_IDLE_SPLIT, IfaceIdleTimeout, b);
! 469: TimerStart(&iface->idleTimer);
! 470: iface->traffic[1] = TRUE;
! 471: iface->traffic[0] = FALSE;
! 472:
! 473: /* Reset statistics */
! 474: memset(&iface->idleStats, 0, sizeof(iface->idleStats));
! 475: }
! 476:
! 477: /* Update interface name and description */
! 478: if (b->params.ifname[0] != 0) {
! 479: if (IfaceSetName(b, b->params.ifname) != -1)
! 480: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
! 481: b->name, iface->ngname, b->params.ifname));
! 482: } else if (iface->conf.ifname[0] != 0) {
! 483: if (IfaceSetName(b, iface->conf.ifname) != -1)
! 484: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
! 485: b->name, iface->ngname, iface->conf.ifname));
! 486: }
! 487: #ifdef SIOCSIFDESCR
! 488: if (b->params.ifdescr != NULL) {
! 489: if (IfaceSetDescr(b, b->params.ifdescr) != -1) {
! 490: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add description \"%s\"",
! 491: b->name, b->params.ifdescr));
! 492: iface->ifdescr = b->params.ifdescr;
! 493: }
! 494: }
! 495: #endif
! 496: #ifdef SIOCAIFGROUP
! 497: if (iface->conf.ifgroup[0] != 0) {
! 498: if (IfaceAddGroup(b, iface->conf.ifgroup) != -1)
! 499: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add group %s to %s",
! 500: b->name, iface->conf.ifgroup, iface->ngname));
! 501: }
! 502: if (b->params.ifgroup[0] != 0) {
! 503: if (IfaceAddGroup(b, b->params.ifgroup) != -1)
! 504: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Add group %s to %s",
! 505: b->name, b->params.ifgroup, iface->ngname));
! 506: }
! 507: #endif
! 508: #ifdef USE_IPFW
! 509: /* Allocate ACLs */
! 510: acls = b->params.acl_pipe;
! 511: poollast = &pipe_pool;
! 512: poollaststart = pipe_pool_start;
! 513: while (acls != NULL) {
! 514: acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
! 515: poollaststart = acls->real_number;
! 516: acls = acls->next;
! 517: };
! 518: acls = b->params.acl_queue;
! 519: poollast = &queue_pool;
! 520: poollaststart = queue_pool_start;
! 521: while (acls != NULL) {
! 522: acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
! 523: poollaststart = acls->real_number;
! 524: acls = acls->next;
! 525: };
! 526: prev_number = -1;
! 527: prev_real_number = -1;
! 528: acls = b->params.acl_table;
! 529: poollast = &table_pool;
! 530: poollaststart = table_pool_start;
! 531: while (acls != NULL) {
! 532: if (acls->real_number == 0) {
! 533: if (acls->number == prev_number) { /* ACL list is presorted so we need not allocate if equal */
! 534: acls->real_number = prev_real_number;
! 535: } else {
! 536: acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
! 537: poollaststart = acls->real_number;
! 538: prev_number = acls->number;
! 539: prev_real_number = acls->real_number;
! 540: }
! 541: }
! 542: acls = acls->next;
! 543: };
! 544: acls = b->params.acl_rule;
! 545: poollast = &rule_pool;
! 546: poollaststart = rule_pool_start;
! 547: while (acls != NULL) {
! 548: acls->real_number = IfaceAllocACL(&poollast, poollaststart, iface->ifname, acls->number);
! 549: poollaststart = acls->real_number;
! 550: acls = acls->next;
! 551: };
! 552:
! 553: /* Set ACLs */
! 554: acls = b->params.acl_pipe;
! 555: while (acls != NULL) {
! 556: ExecCmd(LG_IFACE2, b->name, "%s pipe %d config %s", PATH_IPFW, acls->real_number, acls->rule);
! 557: acls = acls->next;
! 558: }
! 559: acls = b->params.acl_queue;
! 560: while (acls != NULL) {
! 561: buf = IFaceParseACL(acls->rule,iface->ifname);
! 562: ExecCmd(LG_IFACE2, b->name, "%s queue %d config %s", PATH_IPFW, acls->real_number, buf);
! 563: Freee(buf);
! 564: acls = acls->next;
! 565: }
! 566: acls = b->params.acl_table;
! 567: while (acls != NULL) {
! 568: acl = Mdup(MB_IFACE, acls, sizeof(struct acl) + strlen(acls->rule));
! 569: acl->next = iface->tables;
! 570: iface->tables = acl;
! 571: ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acls->real_number, acls->rule);
! 572: acls = acls->next;
! 573: };
! 574: acls = b->params.acl_rule;
! 575: while (acls != NULL) {
! 576: buf = IFaceParseACL(acls->rule, iface->ifname);
! 577: ExecCmd(LG_IFACE2, b->name, "%s add %d %s via %s", PATH_IPFW, acls->real_number, buf, iface->ifname);
! 578: Freee(buf);
! 579: acls = acls->next;
! 580: };
! 581: #endif /* USE_IPFW */
! 582:
! 583: };
! 584:
! 585: /* Bring up system interface */
! 586: IfaceChangeFlags(b, 0, IFF_UP | (ready?0:IFF_LINK0));
! 587:
! 588: /* Send any cached packets */
! 589: IfaceCacheSend(b);
! 590:
! 591: }
! 592:
! 593: /*
! 594: * IfaceDown()
! 595: *
! 596: * Our packet transport mechanism is no longer ready for traffic.
! 597: */
! 598:
! 599: void
! 600: IfaceDown(Bund b)
! 601: {
! 602: IfaceState const iface = &b->iface;
! 603: #ifdef USE_IPFW
! 604: struct acl_pool **rp, *rp1;
! 605: char cb[32768];
! 606: struct acl *acl, *aclnext;
! 607: #endif
! 608:
! 609: Log(LG_IFACE, ("[%s] IFACE: Down event", b->name));
! 610:
! 611: /* Bring down system interface */
! 612: IfaceChangeFlags(b, IFF_UP | IFF_LINK0, 0);
! 613:
! 614: TimerStop(&iface->idleTimer);
! 615: TimerStop(&iface->sessionTimer);
! 616:
! 617: #ifdef USE_IPFW
! 618: /* Remove rule ACLs */
! 619: rp = &rule_pool;
! 620: cb[0]=0;
! 621: while (*rp != NULL) {
! 622: if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
! 623: sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
! 624: rp1 = *rp;
! 625: *rp = (*rp)->next;
! 626: Freee(rp1);
! 627: } else {
! 628: rp = &((*rp)->next);
! 629: };
! 630: };
! 631: if (cb[0]!=0)
! 632: ExecCmdNosh(LG_IFACE2, b->name, "%s delete%s",
! 633: PATH_IPFW, cb);
! 634:
! 635: /* Remove table ACLs */
! 636: rp = &table_pool;
! 637: while (*rp != NULL) {
! 638: if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
! 639: rp1 = *rp;
! 640: *rp = (*rp)->next;
! 641: Freee(rp1);
! 642: } else {
! 643: rp = &((*rp)->next);
! 644: };
! 645: };
! 646: acl = iface->tables;
! 647: while (acl != NULL) {
! 648: ExecCmd(LG_IFACE2, b->name, "%s table %d delete %s",
! 649: PATH_IPFW, acl->real_number, acl->rule);
! 650: aclnext = acl->next;
! 651: Freee(acl);
! 652: acl = aclnext;
! 653: };
! 654: iface->tables = NULL;
! 655:
! 656: /* Remove queue ACLs */
! 657: rp = &queue_pool;
! 658: cb[0]=0;
! 659: while (*rp != NULL) {
! 660: if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
! 661: sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
! 662: rp1 = *rp;
! 663: *rp = (*rp)->next;
! 664: Freee(rp1);
! 665: } else {
! 666: rp = &((*rp)->next);
! 667: };
! 668: };
! 669: if (cb[0]!=0)
! 670: ExecCmdNosh(LG_IFACE2, b->name, "%s queue delete%s",
! 671: PATH_IPFW, cb);
! 672:
! 673: /* Remove pipe ACLs */
! 674: rp = &pipe_pool;
! 675: cb[0]=0;
! 676: while (*rp != NULL) {
! 677: if (strncmp((*rp)->ifname, iface->ifname, IFNAMSIZ) == 0) {
! 678: sprintf(cb+strlen(cb), " %d", (*rp)->real_number);
! 679: rp1 = *rp;
! 680: *rp = (*rp)->next;
! 681: Freee(rp1);
! 682: } else {
! 683: rp = &((*rp)->next);
! 684: };
! 685: };
! 686: if (cb[0]!=0)
! 687: ExecCmdNosh(LG_IFACE2, b->name, "%s pipe delete%s",
! 688: PATH_IPFW, cb);
! 689: #endif /* USE_IPFW */
! 690:
! 691: /* Revert interface name and description */
! 692:
! 693: if (strcmp(iface->ngname, iface->ifname) != 0) {
! 694: if (iface->conf.ifname[0] != 0) {
! 695: /* Restore to config defined */
! 696: if (IfaceSetName(b, iface->conf.ifname) != -1)
! 697: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
! 698: b->name, iface->ifname, iface->conf.ifname));
! 699: } else {
! 700: /* Restore to original interface name */
! 701: if (IfaceSetName(b, iface->ngname) != -1)
! 702: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Rename interface %s to %s",
! 703: b->name, iface->ifname, iface->ngname));
! 704: }
! 705: }
! 706: #ifdef SIOCSIFDESCR
! 707: if (iface->ifdescr != NULL) {
! 708: if (iface->conf.ifdescr != NULL) {
! 709: /* Restore to config defined */
! 710: if (IfaceSetDescr(b, iface->conf.ifdescr) != -1) {
! 711: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Set description \"%s\"",
! 712: b->name, iface->conf.ifdescr));
! 713: iface->ifdescr = iface->conf.ifdescr;
! 714: } else
! 715: iface->ifdescr = NULL;
! 716: } else {
! 717: /* Restore to original (empty) */
! 718: if (IfaceSetDescr(b, "") != -1) {
! 719: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Clear description",
! 720: b->name));
! 721: }
! 722: iface->ifdescr = NULL;
! 723: }
! 724: }
! 725: #endif
! 726: #ifdef SIOCAIFGROUP
! 727: if (b->params.ifgroup[0] != 0) {
! 728: if (IfaceDelGroup(b, b->params.ifgroup) != -1)
! 729: Log(LG_BUND|LG_IFACE, ("[%s] IFACE: Remove group %s from %s",
! 730: b->name, b->params.ifgroup, iface->ngname));
! 731: }
! 732: #endif
! 733: }
! 734:
! 735: /*
! 736: * IfaceListenInput()
! 737: *
! 738: * A packet was received on our demand snooping hook. Stimulate a connection.
! 739: */
! 740:
! 741: void
! 742: IfaceListenInput(Bund b, int proto, Mbuf pkt)
! 743: {
! 744: IfaceState const iface = &b->iface;
! 745: int const isDemand = IfaceIsDemand(proto, pkt);
! 746:
! 747: /* Does this count as demand traffic? */
! 748: if (iface->open && isDemand) {
! 749: iface->traffic[0] = TRUE;
! 750: Log(LG_IFACE, ("[%s] IFACE: Outgoing %s packet demands connection", b->name,
! 751: (proto==PROTO_IP)?"IP":"IPv6"));
! 752: RecordLinkUpDownReason(b, NULL, 1, STR_DEMAND, NULL);
! 753: BundOpen(b);
! 754: IfaceCachePkt(b, proto, pkt);
! 755: } else {
! 756: mbfree(pkt);
! 757: }
! 758: }
! 759:
! 760: #ifdef USE_IPFW
! 761: /*
! 762: * IfaceAllocACL ()
! 763: *
! 764: * Allocates unique real number for new ACL and adds it to the list of used ones.
! 765: */
! 766:
! 767: static int
! 768: IfaceAllocACL(struct acl_pool ***ap, int start, char *ifname, int number)
! 769: {
! 770: int i;
! 771: struct acl_pool **rp,*rp1;
! 772:
! 773: rp1 = Malloc(MB_IFACE, sizeof(struct acl_pool));
! 774: strlcpy(rp1->ifname, ifname, sizeof(rp1->ifname));
! 775: rp1->acl_number = number;
! 776:
! 777: rp = *ap;
! 778: i = start;
! 779: while (*rp != NULL && (*rp)->real_number <= i) {
! 780: i = (*rp)->real_number+1;
! 781: rp = &((*rp)->next);
! 782: };
! 783: if (*rp == NULL) {
! 784: rp1->next = NULL;
! 785: } else {
! 786: rp1->next = *rp;
! 787: };
! 788: rp1->real_number = i;
! 789: *rp = rp1;
! 790: *ap = rp;
! 791: return(i);
! 792: }
! 793:
! 794: /*
! 795: * IfaceFindACL ()
! 796: *
! 797: * Finds ACL in the list and gets its real number.
! 798: */
! 799:
! 800: static int
! 801: IfaceFindACL (struct acl_pool *ap, char * ifname, int number)
! 802: {
! 803: int i;
! 804: struct acl_pool *rp;
! 805:
! 806: rp=ap;
! 807: i=-1;
! 808: while (rp != NULL) {
! 809: if ((rp->acl_number == number) && (strncmp(rp->ifname,ifname,IFNAMSIZ) == 0)) {
! 810: i = rp->real_number;
! 811: break;
! 812: };
! 813: rp = rp->next;
! 814: };
! 815: return(i);
! 816: }
! 817:
! 818: /*
! 819: * IFaceParseACL ()
! 820: *
! 821: * Parces ACL and replaces %r, %p and %q macroses
! 822: * by the real numbers of rules, queues and pipes.
! 823: */
! 824:
! 825: static char *
! 826: IFaceParseACL (char * src, char * ifname)
! 827: {
! 828: char *buf,*buf1;
! 829: char *begin,*param,*end;
! 830: char t;
! 831: int num,real_number;
! 832: struct acl_pool *ap;
! 833:
! 834: buf = Malloc(MB_IFACE, ACL_LEN);
! 835: buf1 = Malloc(MB_IFACE, ACL_LEN);
! 836:
! 837: strlcpy(buf, src, ACL_LEN);
! 838: do {
! 839: end = buf;
! 840: begin = strsep(&end, "%");
! 841: param = strsep(&end, " ");
! 842: if (param != NULL) {
! 843: if (sscanf(param,"%c%d", &t, &num) == 2) {
! 844: switch (t) {
! 845: case 'r':
! 846: ap = rule_pool;
! 847: break;
! 848: case 'p':
! 849: ap = pipe_pool;
! 850: break;
! 851: case 'q':
! 852: ap = queue_pool;
! 853: break;
! 854: case 't':
! 855: ap = table_pool;
! 856: break;
! 857: default:
! 858: ap = NULL;
! 859: };
! 860: real_number = IfaceFindACL(ap,ifname,num);
! 861: if (end != NULL) {
! 862: snprintf(buf1, ACL_LEN, "%s%d %s", begin, real_number, end);
! 863: } else {
! 864: snprintf(buf1, ACL_LEN, "%s%d", begin, real_number);
! 865: };
! 866: strlcpy(buf, buf1, ACL_LEN);
! 867: };
! 868: };
! 869: } while (end != NULL);
! 870: Freee(buf1);
! 871: return(buf);
! 872: }
! 873: #endif /* USE_IPFW */
! 874:
! 875: /*
! 876: * IfaceIpIfaceUp()
! 877: *
! 878: * Bring up the IP interface. The "ready" flag means that
! 879: * IPCP is also up and we can deliver packets immediately.
! 880: */
! 881:
! 882: int
! 883: IfaceIpIfaceUp(Bund b, int ready)
! 884: {
! 885: IfaceState const iface = &b->iface;
! 886: struct sockaddr_dl hwa;
! 887: char hisaddr[20];
! 888: IfaceRoute r;
! 889: u_char *ether;
! 890:
! 891: if (ready && !iface->conf.self_addr_force) {
! 892: in_addrtou_range(&b->ipcp.want_addr, 32, &iface->self_addr);
! 893: } else {
! 894: u_rangecopy(&iface->conf.self_addr, &iface->self_addr);
! 895: }
! 896: if (ready && !iface->conf.peer_addr_force) {
! 897: in_addrtou_addr(&b->ipcp.peer_addr, &iface->peer_addr);
! 898: } else {
! 899: u_addrcopy(&iface->conf.peer_addr, &iface->peer_addr);
! 900: }
! 901:
! 902: if (IfaceNgIpInit(b, ready)) {
! 903: Log(LG_ERR, ("[%s] IFACE: IfaceNgIpInit() error, closing IPCP", b->name));
! 904: FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
! 905: return (-1);
! 906: };
! 907:
! 908: /* Set addresses */
! 909: if (!u_rangeempty(&iface->self_addr) &&
! 910: IfaceChangeAddr(b, 1, &iface->self_addr, &iface->peer_addr)) {
! 911: Log(LG_ERR, ("[%s] IFACE: IfaceChangeAddr() error, closing IPCP", b->name));
! 912: FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
! 913: return (-1);
! 914: };
! 915:
! 916: /* Proxy ARP for peer if desired and peer's address is known */
! 917: u_addrclear(&iface->proxy_addr);
! 918: if (Enabled(&iface->options, IFACE_CONF_PROXY)) {
! 919: if (u_addrempty(&iface->peer_addr)) {
! 920: Log(LG_IFACE,
! 921: ("[%s] IFACE: Can't proxy arp for %s",
! 922: b->name, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr))));
! 923: } else if (GetEther(&iface->peer_addr, &hwa) < 0) {
! 924: Log(LG_IFACE,
! 925: ("[%s] IFACE: No interface to proxy arp on for %s",
! 926: b->name, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr))));
! 927: } else {
! 928: ether = (u_char *) LLADDR(&hwa);
! 929: if (ExecCmdNosh(LG_IFACE2, b->name,
! 930: "%s -S %s %x:%x:%x:%x:%x:%x pub",
! 931: PATH_ARP, u_addrtoa(&iface->peer_addr,hisaddr,sizeof(hisaddr)),
! 932: ether[0], ether[1], ether[2],
! 933: ether[3], ether[4], ether[5]) == 0)
! 934: iface->proxy_addr = iface->peer_addr;
! 935: }
! 936: }
! 937:
! 938: /* Add static routes */
! 939: SLIST_FOREACH(r, &iface->routes, next) {
! 940: if (u_rangefamily(&r->dest)==AF_INET) {
! 941: r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0);
! 942: }
! 943: }
! 944: /* Add dynamic routes */
! 945: SLIST_FOREACH(r, &b->params.routes, next) {
! 946: if (u_rangefamily(&r->dest)==AF_INET) {
! 947: r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_addr) == 0);
! 948: }
! 949: }
! 950:
! 951: #ifdef USE_NG_NAT
! 952: /* Set NAT IP */
! 953: if (iface->nat_up)
! 954: IfaceSetupNAT(b);
! 955: #endif
! 956:
! 957: /* Call "up" script */
! 958: if (*iface->up_script) {
! 959: char selfbuf[40],peerbuf[40];
! 960: char ns1buf[21], ns2buf[21];
! 961: int res;
! 962:
! 963: if(b->ipcp.want_dns[0].s_addr != 0)
! 964: snprintf(ns1buf, sizeof(ns1buf), "dns1 %s", inet_ntoa(b->ipcp.want_dns[0]));
! 965: else
! 966: ns1buf[0] = '\0';
! 967: if(b->ipcp.want_dns[1].s_addr != 0)
! 968: snprintf(ns2buf, sizeof(ns2buf), "dns2 %s", inet_ntoa(b->ipcp.want_dns[1]));
! 969: else
! 970: ns2buf[0] = '\0';
! 971:
! 972: res = ExecCmd(LG_IFACE2, b->name, "%s %s inet %s %s '%s' '%s' '%s' '%s'",
! 973: iface->up_script, iface->ifname, u_rangetoa(&iface->self_addr,selfbuf, sizeof(selfbuf)),
! 974: u_addrtoa(&iface->peer_addr, peerbuf, sizeof(peerbuf)),
! 975: *b->params.authname ? b->params.authname : "-",
! 976: ns1buf, ns2buf, *b->params.peeraddr ? b->params.peeraddr : "-");
! 977: if (res != 0) {
! 978: FsmFailure(&b->ipcp.fsm, FAIL_NEGOT_FAILURE);
! 979: return (-1);
! 980: }
! 981: }
! 982: return (0);
! 983: }
! 984:
! 985: /*
! 986: * IfaceIpIfaceDown()
! 987: *
! 988: * Bring down the IP interface. This implies we're no longer ready.
! 989: */
! 990:
! 991: void
! 992: IfaceIpIfaceDown(Bund b)
! 993: {
! 994: IfaceState const iface = &b->iface;
! 995: IfaceRoute r;
! 996: char buf[48];
! 997:
! 998: /* Call "down" script */
! 999: if (*iface->down_script) {
! 1000: char selfbuf[40],peerbuf[40];
! 1001:
! 1002: ExecCmd(LG_IFACE2, b->name, "%s %s inet %s %s '%s' '%s'",
! 1003: iface->down_script, iface->ifname, u_rangetoa(&iface->self_addr,selfbuf, sizeof(selfbuf)),
! 1004: u_addrtoa(&iface->peer_addr, peerbuf, sizeof(peerbuf)),
! 1005: *b->params.authname ? b->params.authname : "-",
! 1006: *b->params.peeraddr ? b->params.peeraddr : "-");
! 1007: }
! 1008:
! 1009: /* Delete dynamic routes */
! 1010: SLIST_FOREACH(r, &b->params.routes, next) {
! 1011: if (u_rangefamily(&r->dest)==AF_INET) {
! 1012: if (!r->ok)
! 1013: continue;
! 1014: IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr);
! 1015: r->ok = 0;
! 1016: }
! 1017: }
! 1018: /* Delete static routes */
! 1019: SLIST_FOREACH(r, &iface->routes, next) {
! 1020: if (u_rangefamily(&r->dest)==AF_INET) {
! 1021: if (!r->ok)
! 1022: continue;
! 1023: IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_addr);
! 1024: r->ok = 0;
! 1025: }
! 1026: }
! 1027:
! 1028: /* Delete any proxy arp entry */
! 1029: if (!u_addrempty(&iface->proxy_addr))
! 1030: ExecCmdNosh(LG_IFACE2, b->name, "%s -d %s", PATH_ARP, u_addrtoa(&iface->proxy_addr, buf, sizeof(buf)));
! 1031: u_addrclear(&iface->proxy_addr);
! 1032:
! 1033: /* Remove address from interface */
! 1034: if (!u_rangeempty(&iface->self_addr))
! 1035: IfaceChangeAddr(b, 0, &iface->self_addr, &iface->peer_addr);
! 1036:
! 1037: IfaceNgIpShutdown(b);
! 1038: }
! 1039:
! 1040: /*
! 1041: * IfaceIpv6IfaceUp()
! 1042: *
! 1043: * Bring up the IPv6 interface. The "ready" flag means that
! 1044: * IPv6CP is also up and we can deliver packets immediately.
! 1045: */
! 1046:
! 1047: int
! 1048: IfaceIpv6IfaceUp(Bund b, int ready)
! 1049: {
! 1050: IfaceState const iface = &b->iface;
! 1051: IfaceRoute r;
! 1052:
! 1053: if (ready && !iface->conf.self_ipv6_addr_force) {
! 1054: iface->self_ipv6_addr.family = AF_INET6;
! 1055: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[0] = 0x80fe; /* Network byte order */
! 1056: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[1] = 0x0000;
! 1057: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[2] = 0x0000;
! 1058: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[3] = 0x0000;
! 1059: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[4] = ((u_short*)b->ipv6cp.myintid)[0];
! 1060: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[5] = ((u_short*)b->ipv6cp.myintid)[1];
! 1061: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[6] = ((u_short*)b->ipv6cp.myintid)[2];
! 1062: iface->self_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[7] = ((u_short*)b->ipv6cp.myintid)[3];
! 1063: } else {
! 1064: u_addrcopy(&iface->conf.self_ipv6_addr, &iface->self_ipv6_addr);
! 1065: }
! 1066: if (ready && !iface->conf.peer_ipv6_addr_force) {
! 1067: iface->peer_ipv6_addr.family = AF_INET6;
! 1068: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[0] = 0x80fe; /* Network byte order */
! 1069: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[1] = 0x0000;
! 1070: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[2] = 0x0000;
! 1071: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[3] = 0x0000;
! 1072: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[4] = ((u_short*)b->ipv6cp.hisintid)[0];
! 1073: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[5] = ((u_short*)b->ipv6cp.hisintid)[1];
! 1074: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[6] = ((u_short*)b->ipv6cp.hisintid)[2];
! 1075: iface->peer_ipv6_addr.u.ip6.__u6_addr.__u6_addr16[7] = ((u_short*)b->ipv6cp.hisintid)[3];
! 1076: } else {
! 1077: u_addrcopy(&iface->conf.peer_ipv6_addr, &iface->peer_ipv6_addr);
! 1078: }
! 1079:
! 1080: if (IfaceNgIpv6Init(b, ready)) {
! 1081: Log(LG_ERR, ("[%s] IFACE: IfaceNgIpv6Init() failed, closing IPv6CP", b->name));
! 1082: FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
! 1083: return (-1);
! 1084: };
! 1085:
! 1086: /* Set addresses */
! 1087: if (!u_addrempty(&iface->self_ipv6_addr)) {
! 1088: struct u_range rng;
! 1089: rng.addr = iface->self_ipv6_addr;
! 1090: rng.width = 64;
! 1091: if (IfaceChangeAddr(b, 1, &rng, &iface->peer_ipv6_addr)) {
! 1092: Log(LG_ERR, ("[%s] IFACE: IfaceChangeAddr() failed, closing IPv6CP", b->name));
! 1093: FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
! 1094: return (-1);
! 1095: }
! 1096: };
! 1097:
! 1098: /* Add static routes */
! 1099: SLIST_FOREACH(r, &iface->routes, next) {
! 1100: if (u_rangefamily(&r->dest)==AF_INET6) {
! 1101: r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0);
! 1102: }
! 1103: }
! 1104: /* Add dynamic routes */
! 1105: SLIST_FOREACH(r, &b->params.routes, next) {
! 1106: if (u_rangefamily(&r->dest)==AF_INET6) {
! 1107: r->ok = (IfaceSetRoute(b, RTM_ADD, &r->dest, &iface->peer_ipv6_addr) == 0);
! 1108: }
! 1109: }
! 1110:
! 1111: /* Call "up" script */
! 1112: if (*iface->up_script) {
! 1113: char selfbuf[48],peerbuf[48];
! 1114: int res;
! 1115:
! 1116: res = ExecCmd(LG_IFACE2, b->name, "%s %s inet6 %s%%%s %s%%%s '%s' '%s'",
! 1117: iface->up_script, iface->ifname,
! 1118: u_addrtoa(&iface->self_ipv6_addr, selfbuf, sizeof(selfbuf)), iface->ifname,
! 1119: u_addrtoa(&iface->peer_ipv6_addr, peerbuf, sizeof(peerbuf)), iface->ifname,
! 1120: *b->params.authname ? b->params.authname : "-",
! 1121: *b->params.peeraddr ? b->params.peeraddr : "-");
! 1122: if (res != 0) {
! 1123: FsmFailure(&b->ipv6cp.fsm, FAIL_NEGOT_FAILURE);
! 1124: return (-1);
! 1125: }
! 1126: }
! 1127: return (0);
! 1128:
! 1129: }
! 1130:
! 1131: /*
! 1132: * IfaceIpv6IfaceDown()
! 1133: *
! 1134: * Bring down the IPv6 interface. This implies we're no longer ready.
! 1135: */
! 1136:
! 1137: void
! 1138: IfaceIpv6IfaceDown(Bund b)
! 1139: {
! 1140: IfaceState const iface = &b->iface;
! 1141: IfaceRoute r;
! 1142: struct u_range rng;
! 1143:
! 1144: /* Call "down" script */
! 1145: if (*iface->down_script) {
! 1146: char selfbuf[48],peerbuf[48];
! 1147:
! 1148: ExecCmd(LG_IFACE2, b->name, "%s %s inet6 %s%%%s %s%%%s '%s' '%s'",
! 1149: iface->down_script, iface->ifname,
! 1150: u_addrtoa(&iface->self_ipv6_addr, selfbuf, sizeof(selfbuf)), iface->ifname,
! 1151: u_addrtoa(&iface->peer_ipv6_addr, peerbuf, sizeof(peerbuf)), iface->ifname,
! 1152: *b->params.authname ? b->params.authname : "-",
! 1153: *b->params.peeraddr ? b->params.peeraddr : "-");
! 1154: }
! 1155:
! 1156: /* Delete dynamic routes */
! 1157: SLIST_FOREACH(r, &b->params.routes, next) {
! 1158: if (u_rangefamily(&r->dest)==AF_INET6) {
! 1159: if (!r->ok)
! 1160: continue;
! 1161: IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr);
! 1162: r->ok = 0;
! 1163: }
! 1164: }
! 1165: /* Delete static routes */
! 1166: SLIST_FOREACH(r, &iface->routes, next) {
! 1167: if (u_rangefamily(&r->dest)==AF_INET6) {
! 1168: if (!r->ok)
! 1169: continue;
! 1170: IfaceSetRoute(b, RTM_DELETE, &r->dest, &iface->peer_ipv6_addr);
! 1171: r->ok = 0;
! 1172: }
! 1173: }
! 1174:
! 1175: if (!u_addrempty(&iface->self_ipv6_addr)) {
! 1176: /* Remove address from interface */
! 1177: rng.addr = iface->self_ipv6_addr;
! 1178: rng.width = 64;
! 1179: IfaceChangeAddr(b, 0, &rng, &iface->peer_ipv6_addr);
! 1180: }
! 1181:
! 1182: IfaceNgIpv6Shutdown(b);
! 1183: }
! 1184:
! 1185: /*
! 1186: * IfaceIdleTimeout()
! 1187: */
! 1188:
! 1189: static void
! 1190: IfaceIdleTimeout(void *arg)
! 1191: {
! 1192: Bund b = (Bund)arg;
! 1193:
! 1194: IfaceState const iface = &b->iface;
! 1195: int k;
! 1196:
! 1197: /* Get updated bpf node traffic statistics */
! 1198: BundUpdateStats(b);
! 1199:
! 1200: /* Mark current traffic period if there was traffic */
! 1201: if (iface->idleStats.recvFrames + iface->idleStats.xmitFrames <
! 1202: b->stats.recvFrames + b->stats.xmitFrames) {
! 1203: iface->traffic[0] = TRUE;
! 1204: } else { /* no demand traffic for a whole idle timeout period? */
! 1205: for (k = 0; k < IFACE_IDLE_SPLIT && !iface->traffic[k]; k++);
! 1206: if (k == IFACE_IDLE_SPLIT) {
! 1207: Log(LG_BUND, ("[%s] IFACE: Idle timeout", b->name));
! 1208: RecordLinkUpDownReason(b, NULL, 0, STR_IDLE_TIMEOUT, NULL);
! 1209: BundClose(b);
! 1210: return;
! 1211: }
! 1212: }
! 1213:
! 1214: iface->idleStats = b->stats;
! 1215:
! 1216: /* Shift traffic history */
! 1217: memmove(iface->traffic + 1,
! 1218: iface->traffic, (IFACE_IDLE_SPLIT - 1) * sizeof(*iface->traffic));
! 1219: iface->traffic[0] = FALSE;
! 1220:
! 1221: /* Restart timer */
! 1222: TimerStart(&iface->idleTimer);
! 1223: }
! 1224:
! 1225: /*
! 1226: * IfaceSessionTimeout()
! 1227: */
! 1228:
! 1229: static void
! 1230: IfaceSessionTimeout(void *arg)
! 1231: {
! 1232: Bund b = (Bund)arg;
! 1233:
! 1234: Log(LG_BUND, ("[%s] IFACE: Session timeout", b->name));
! 1235:
! 1236: RecordLinkUpDownReason(b, NULL, 0, STR_SESSION_TIMEOUT, NULL);
! 1237:
! 1238: BundClose(b);
! 1239:
! 1240: }
! 1241:
! 1242: /*
! 1243: * IfaceCachePkt()
! 1244: *
! 1245: * A packet caused dial-on-demand; save it for later if possible.
! 1246: * Consumes the mbuf in any case.
! 1247: */
! 1248:
! 1249: static void
! 1250: IfaceCachePkt(Bund b, int proto, Mbuf pkt)
! 1251: {
! 1252: IfaceState const iface = &b->iface;
! 1253:
! 1254: /* Only cache network layer data */
! 1255: if (!PROT_NETWORK_DATA(proto)) {
! 1256: mbfree(pkt);
! 1257: return;
! 1258: }
! 1259:
! 1260: /* Release previously cached packet, if any, and save this one */
! 1261: if (iface->dodCache.pkt)
! 1262: mbfree(iface->dodCache.pkt);
! 1263:
! 1264: iface->dodCache.pkt = pkt;
! 1265: iface->dodCache.proto = proto;
! 1266: iface->dodCache.ts = time(NULL);
! 1267: }
! 1268:
! 1269: /*
! 1270: * IfaceCacheSend()
! 1271: *
! 1272: * Send cached packet
! 1273: */
! 1274:
! 1275: static void
! 1276: IfaceCacheSend(Bund b)
! 1277: {
! 1278: IfaceState const iface = &b->iface;
! 1279:
! 1280: if (iface->dodCache.pkt) {
! 1281: if (iface->dodCache.ts + MAX_DOD_CACHE_DELAY < time(NULL))
! 1282: mbfree(iface->dodCache.pkt);
! 1283: else {
! 1284: if (NgFuncWritePppFrame(b, NG_PPP_BUNDLE_LINKNUM,
! 1285: iface->dodCache.proto, iface->dodCache.pkt) < 0) {
! 1286: Perror("[%s] can't write cached pkt", b->name);
! 1287: }
! 1288: }
! 1289: iface->dodCache.pkt = NULL;
! 1290: }
! 1291: }
! 1292:
! 1293: /*
! 1294: * IfaceIsDemand()
! 1295: *
! 1296: * Determine if this outgoing packet qualifies for dial-on-demand
! 1297: */
! 1298:
! 1299: static int
! 1300: IfaceIsDemand(int proto, Mbuf pkt)
! 1301: {
! 1302: switch (proto) {
! 1303: case PROTO_IP:
! 1304: {
! 1305: struct ip *ip;
! 1306:
! 1307: if (MBLEN(pkt) < sizeof(struct ip))
! 1308: return (0);
! 1309:
! 1310: ip = (struct ip *)MBDATA(pkt);
! 1311: switch (ip->ip_p) {
! 1312: case IPPROTO_IGMP: /* No multicast stuff */
! 1313: return(0);
! 1314: #if (!defined(__FreeBSD__) || __FreeBSD_version >= 600025)
! 1315: case IPPROTO_ICMP:
! 1316: {
! 1317: struct icmphdr *icmp;
! 1318:
! 1319: if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct icmphdr)))
! 1320: return (0);
! 1321:
! 1322: icmp = (struct icmphdr *) ((u_int32_t *) ip + ip->ip_hl);
! 1323:
! 1324: switch (icmp->icmp_type) /* No ICMP replies */
! 1325: {
! 1326: case ICMP_ECHOREPLY:
! 1327: case ICMP_UNREACH:
! 1328: case ICMP_REDIRECT:
! 1329: return(0);
! 1330: default:
! 1331: break;
! 1332: }
! 1333: }
! 1334: break;
! 1335: #endif
! 1336: case IPPROTO_UDP:
! 1337: {
! 1338: struct udphdr *udp;
! 1339:
! 1340: if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct udphdr)))
! 1341: return (0);
! 1342:
! 1343: udp = (struct udphdr *) ((u_int32_t *) ip + ip->ip_hl);
! 1344:
! 1345: #define NTP_PORT 123
! 1346: if (ntohs(udp->uh_dport) == NTP_PORT) /* No NTP packets */
! 1347: return(0);
! 1348: }
! 1349: break;
! 1350: case IPPROTO_TCP:
! 1351: {
! 1352: struct tcphdr *tcp;
! 1353:
! 1354: if (MBLEN(pkt) < (ip->ip_hl * 4 + sizeof(struct tcphdr)))
! 1355: return (0);
! 1356:
! 1357: tcp = (struct tcphdr *) ((u_int32_t *) ip + ip->ip_hl);
! 1358:
! 1359: if (tcp->th_flags & TH_RST) /* No TCP reset packets */
! 1360: return(0);
! 1361: }
! 1362: break;
! 1363: default:
! 1364: break;
! 1365: }
! 1366: break;
! 1367: }
! 1368: default:
! 1369: break;
! 1370: }
! 1371: return(1);
! 1372: }
! 1373:
! 1374: /*
! 1375: * IfaceSetCommand()
! 1376: */
! 1377:
! 1378: static int
! 1379: IfaceSetCommand(Context ctx, int ac, char *av[], void *arg)
! 1380: {
! 1381: IfaceState const iface = &ctx->bund->iface;
! 1382: int empty_arg;
! 1383:
! 1384: switch ((intptr_t)arg) {
! 1385: case SET_NAME:
! 1386: #ifdef SIOCSIFDESCR
! 1387: case SET_DESCR:
! 1388: #endif
! 1389: case SET_UP_SCRIPT:
! 1390: case SET_DOWN_SCRIPT:
! 1391: empty_arg = TRUE;
! 1392: break;
! 1393: default:
! 1394: empty_arg = FALSE;
! 1395: break;
! 1396: }
! 1397:
! 1398: if ((ac == 0) && (empty_arg == FALSE))
! 1399: return(-1);
! 1400: switch ((intptr_t)arg) {
! 1401: case SET_IDLE:
! 1402: iface->idle_timeout = atoi(*av);
! 1403: break;
! 1404: case SET_SESSION:
! 1405: iface->session_timeout = atoi(*av);
! 1406: break;
! 1407: case SET_ADDRS:
! 1408: {
! 1409: struct u_range self_addr;
! 1410: struct u_addr peer_addr;
! 1411: int self_addr_force = 0, peer_addr_force = 0;
! 1412: char *arg;
! 1413:
! 1414: /* Parse */
! 1415: if (ac != 2)
! 1416: return(-1);
! 1417: arg = av[0];
! 1418: if (arg[0] == '!') {
! 1419: self_addr_force = 1;
! 1420: arg++;
! 1421: }
! 1422: if (!ParseRange(arg, &self_addr, ALLOW_IPV4|ALLOW_IPV6))
! 1423: Error("Bad IP address \"%s\"", av[0]);
! 1424: arg = av[1];
! 1425: if (arg[0] == '!') {
! 1426: peer_addr_force = 1;
! 1427: arg++;
! 1428: }
! 1429: if (!ParseAddr(arg, &peer_addr, ALLOW_IPV4|ALLOW_IPV6))
! 1430: Error("Bad IP address \"%s\"", av[1]);
! 1431: if (self_addr.addr.family != peer_addr.family)
! 1432: Error("Addresses must be from the same protocol family");
! 1433:
! 1434: /* OK */
! 1435: if (peer_addr.family == AF_INET) {
! 1436: iface->conf.self_addr = self_addr;
! 1437: iface->conf.peer_addr = peer_addr;
! 1438: iface->conf.self_addr_force = self_addr_force;
! 1439: iface->conf.peer_addr_force = peer_addr_force;
! 1440: } else {
! 1441: iface->conf.self_ipv6_addr = self_addr.addr;
! 1442: iface->conf.peer_ipv6_addr = peer_addr;
! 1443: iface->conf.self_ipv6_addr_force = self_addr_force;
! 1444: iface->conf.peer_ipv6_addr_force = peer_addr_force;
! 1445: }
! 1446: }
! 1447: break;
! 1448:
! 1449: case SET_ROUTE:
! 1450: {
! 1451: struct u_range range;
! 1452: IfaceRoute r;
! 1453:
! 1454: /* Check */
! 1455: if (ac != 1)
! 1456: return(-1);
! 1457:
! 1458: /* Get dest address */
! 1459: if (!strcasecmp(av[0], "default")) {
! 1460: u_rangeclear(&range);
! 1461: range.addr.family=AF_INET;
! 1462: }
! 1463: else if (!ParseRange(av[0], &range, ALLOW_IPV4|ALLOW_IPV6))
! 1464: Error("Bad route dest address \"%s\"", av[0]);
! 1465: r = Malloc(MB_IFACE, sizeof(struct ifaceroute));
! 1466: r->dest = range;
! 1467: r->ok = 0;
! 1468: SLIST_INSERT_HEAD(&iface->routes, r, next);
! 1469: }
! 1470: break;
! 1471:
! 1472: case SET_MTU:
! 1473: {
! 1474: int max_mtu;
! 1475:
! 1476: /* Check */
! 1477: if (ac != 1)
! 1478: return(-1);
! 1479:
! 1480: max_mtu = atoi(av[0]);
! 1481: if (max_mtu < IFACE_MIN_MTU || max_mtu > IFACE_MAX_MTU)
! 1482: Error("Invalid interface mtu %d", max_mtu);
! 1483: iface->max_mtu = max_mtu;
! 1484: }
! 1485: break;
! 1486:
! 1487: case SET_NAME:
! 1488: switch (ac) {
! 1489: case 0:
! 1490: /* Restore original interface name */
! 1491: if (strcmp(iface->ifname, iface->ngname) != 0) {
! 1492: iface->conf.ifname[0] = '\0';
! 1493: return IfaceSetName(ctx->bund, iface->ngname);
! 1494: }
! 1495: break;
! 1496: case 1:
! 1497: if (strcmp(iface->ifname, av[0]) != 0) {
! 1498: int ifmaxlen = IF_NAMESIZE - ctx->bund->tmpl * IFNUMLEN;
! 1499: if (strlen(av[0]) >= ifmaxlen)
! 1500: Error("Interface name too long, >%d characters", ifmaxlen-1);
! 1501: if ((strncmp(av[0], "ng", 2) == 0) &&
! 1502: ((ctx->bund->tmpl && av[0][2] == 0) ||
! 1503: (av[0][2] >= '0' && av[0][2] <= '9')))
! 1504: Error("This interface name is reserved");
! 1505: strlcpy(iface->conf.ifname, av[0], sizeof(iface->conf.ifname));
! 1506: return IfaceSetName(ctx->bund, av[0]);
! 1507: }
! 1508: break;
! 1509: default:
! 1510: return(-1);
! 1511: }
! 1512: break;
! 1513: #ifdef SIOCSIFDESCR
! 1514: case SET_DESCR:
! 1515: if (ctx->bund->tmpl)
! 1516: Error("Impossible to apply on template");
! 1517: if (iface->conf.ifdescr != NULL)
! 1518: Freee(iface->conf.ifdescr);
! 1519: iface->conf.ifdescr = NULL;
! 1520: iface->ifdescr = NULL;
! 1521: switch (ac) {
! 1522: case 0:
! 1523: return IfaceSetDescr(ctx->bund, "");
! 1524: break;
! 1525: case 1:
! 1526: iface->conf.ifdescr = Mstrdup(MB_IFACE, av[0]);
! 1527: if (IfaceSetDescr(ctx->bund, av[0]) == 0) {
! 1528: iface->ifdescr = iface->conf.ifdescr;
! 1529: return(0);
! 1530: } else
! 1531: return(-1);
! 1532: break;
! 1533: default:
! 1534: return(-1);
! 1535: }
! 1536: break;
! 1537: #endif
! 1538: #ifdef SIOCAIFGROUP
! 1539: case SET_GROUP:
! 1540: if (ac != 1)
! 1541: return(-1);
! 1542:
! 1543: if (av[0][0] && isdigit(av[0][strlen(av[0]) - 1]))
! 1544: Error("Groupnames may not end in a digit");
! 1545: if (strlen(av[0]) >= IFNAMSIZ)
! 1546: Error("Group name %s too long", av[0]);
! 1547: if (iface->conf.ifgroup[0] != 0)
! 1548: IfaceDelGroup(ctx->bund, iface->conf.ifgroup);
! 1549: strlcpy(iface->conf.ifgroup, av[0], IFNAMSIZ);
! 1550: return IfaceAddGroup(ctx->bund, av[0]);
! 1551: break;
! 1552: #endif
! 1553: case SET_UP_SCRIPT:
! 1554: switch (ac) {
! 1555: case 0:
! 1556: *iface->up_script = 0;
! 1557: break;
! 1558: case 1:
! 1559: strlcpy(iface->up_script, av[0], sizeof(iface->up_script));
! 1560: break;
! 1561: default:
! 1562: return(-1);
! 1563: }
! 1564: break;
! 1565:
! 1566: case SET_DOWN_SCRIPT:
! 1567: switch (ac) {
! 1568: case 0:
! 1569: *iface->down_script = 0;
! 1570: break;
! 1571: case 1:
! 1572: strlcpy(iface->down_script, av[0], sizeof(iface->down_script));
! 1573: break;
! 1574: default:
! 1575: return(-1);
! 1576: }
! 1577: break;
! 1578:
! 1579: case SET_ENABLE:
! 1580: EnableCommand(ac, av, &iface->options, gConfList);
! 1581: break;
! 1582:
! 1583: case SET_DISABLE:
! 1584: DisableCommand(ac, av, &iface->options, gConfList);
! 1585: break;
! 1586:
! 1587: default:
! 1588: assert(0);
! 1589: }
! 1590: return(0);
! 1591: }
! 1592:
! 1593: /*
! 1594: * IfaceStat()
! 1595: */
! 1596:
! 1597: int
! 1598: IfaceStat(Context ctx, int ac, char *av[], void *arg)
! 1599: {
! 1600: Bund const b = ctx->bund;
! 1601: IfaceState const iface = &b->iface;
! 1602: IfaceRoute r;
! 1603: #ifdef USE_NG_BPF
! 1604: int k;
! 1605: #endif
! 1606: char buf[48];
! 1607: #if defined(USE_NG_BPF) || defined(USE_IPFW)
! 1608: struct acl *a;
! 1609: #endif
! 1610:
! 1611: Printf("Interface configuration:\r\n");
! 1612: Printf("\tName : %s\r\n", iface->conf.ifname);
! 1613: #ifdef SIOCSIFDESCR
! 1614: Printf("\tDescription : \"%s\"\r\n",
! 1615: (iface->conf.ifdescr != NULL) ? iface->conf.ifdescr : "<none>");
! 1616: #endif
! 1617: #ifdef SIOCAIFGROUP
! 1618: Printf("\tGroup : %s\r\n", iface->conf.ifgroup);
! 1619: #endif
! 1620: Printf("\tMaximum MTU : %d bytes\r\n", iface->max_mtu);
! 1621: Printf("\tIdle timeout : %d seconds\r\n", iface->idle_timeout);
! 1622: Printf("\tSession timeout : %d seconds\r\n", iface->session_timeout);
! 1623: if (!u_rangeempty(&iface->conf.self_addr)) {
! 1624: Printf("\tIP Addresses : %s%s -> ", iface->conf.self_addr_force?"!":"",
! 1625: u_rangetoa(&iface->conf.self_addr,buf,sizeof(buf)));
! 1626: Printf("%s%s\r\n", iface->conf.peer_addr_force?"!":"",
! 1627: u_addrtoa(&iface->conf.peer_addr,buf,sizeof(buf)));
! 1628: }
! 1629: if (!u_addrempty(&iface->conf.self_ipv6_addr)) {
! 1630: Printf("\tIPv6 Addresses : %s%s%%%s -> ", iface->conf.self_ipv6_addr_force?"!":"",
! 1631: u_addrtoa(&iface->conf.self_ipv6_addr,buf,sizeof(buf)), iface->ifname);
! 1632: Printf("%s%s%%%s\r\n", iface->conf.peer_ipv6_addr_force?"!":"",
! 1633: u_addrtoa(&iface->conf.peer_ipv6_addr,buf,sizeof(buf)), iface->ifname);
! 1634: }
! 1635: Printf("\tEvent scripts\r\n");
! 1636: Printf("\t up-script : \"%s\"\r\n",
! 1637: *iface->up_script ? iface->up_script : "<none>");
! 1638: Printf("\t down-script : \"%s\"\r\n",
! 1639: *iface->down_script ? iface->down_script : "<none>");
! 1640: Printf("Interface options:\r\n");
! 1641: OptStat(ctx, &iface->options, gConfList);
! 1642: if (!SLIST_EMPTY(&iface->routes)) {
! 1643: Printf("Static routes via peer:\r\n");
! 1644: SLIST_FOREACH(r, &iface->routes, next) {
! 1645: Printf("\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
! 1646: }
! 1647: }
! 1648: Printf("Interface status:\r\n");
! 1649: Printf("\tAdmin status : %s\r\n", iface->open ? "OPEN" : "CLOSED");
! 1650: Printf("\tStatus : %s\r\n", iface->up ? (iface->dod?"DoD":"UP") : "DOWN");
! 1651: Printf("\tName : %s\r\n", iface->ifname);
! 1652: #ifdef SIOCSIFDESCR
! 1653: Printf("\tDescription : \"%s\"\r\n",
! 1654: (iface->ifdescr != NULL) ? iface->ifdescr : "<none>");
! 1655: #endif
! 1656: if (iface->up) {
! 1657: Printf("\tSession time : %ld seconds\r\n", (long int)(time(NULL) - iface->last_up));
! 1658: if (b->params.idle_timeout || iface->idle_timeout)
! 1659: Printf("\tIdle timeout : %d seconds\r\n", b->params.idle_timeout?b->params.idle_timeout:iface->idle_timeout);
! 1660: if (b->params.session_timeout || iface->session_timeout)
! 1661: Printf("\tSession timeout : %d seconds\r\n", b->params.session_timeout?b->params.session_timeout:iface->session_timeout);
! 1662: Printf("\tMTU : %d bytes\r\n", iface->mtu);
! 1663: }
! 1664: if (iface->ip_up && !u_rangeempty(&iface->self_addr)) {
! 1665: Printf("\tIP Addresses : %s -> ", u_rangetoa(&iface->self_addr,buf,sizeof(buf)));
! 1666: Printf("%s\r\n", u_addrtoa(&iface->peer_addr,buf,sizeof(buf)));
! 1667: }
! 1668: if (iface->ipv6_up && !u_addrempty(&iface->self_ipv6_addr)) {
! 1669: Printf("\tIPv6 Addresses : %s%%%s -> ",
! 1670: u_addrtoa(&iface->self_ipv6_addr,buf,sizeof(buf)), iface->ifname);
! 1671: Printf("%s%%%s\r\n", u_addrtoa(&iface->peer_ipv6_addr,buf,sizeof(buf)), iface->ifname);
! 1672: }
! 1673: if (iface->up) {
! 1674: Printf("Dynamic routes via peer:\r\n");
! 1675: SLIST_FOREACH(r, &ctx->bund->params.routes, next) {
! 1676: Printf("\t%s\r\n", u_rangetoa(&r->dest,buf,sizeof(buf)));
! 1677: }
! 1678: #ifdef USE_IPFW
! 1679: Printf("IPFW pipes:\r\n");
! 1680: a = ctx->bund->params.acl_pipe;
! 1681: while (a) {
! 1682: Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
! 1683: a = a->next;
! 1684: }
! 1685: Printf("IPFW queues:\r\n");
! 1686: a = ctx->bund->params.acl_queue;
! 1687: while (a) {
! 1688: Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
! 1689: a = a->next;
! 1690: }
! 1691: Printf("IPFW tables:\r\n");
! 1692: a = ctx->bund->params.acl_table;
! 1693: while (a) {
! 1694: if (a->number != 0)
! 1695: Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
! 1696: else
! 1697: Printf("\t(%d)\t: '%s'\r\n", a->real_number, a->rule);
! 1698: a = a->next;
! 1699: }
! 1700: Printf("IPFW rules:\r\n");
! 1701: a = ctx->bund->params.acl_rule;
! 1702: while (a) {
! 1703: Printf("\t%d (%d)\t: '%s'\r\n", a->number, a->real_number, a->rule);
! 1704: a = a->next;
! 1705: }
! 1706: #endif /* USE_IPFW */
! 1707: #ifdef USE_NG_BPF
! 1708: Printf("Traffic filters:\r\n");
! 1709: for (k = 0; k < ACL_FILTERS; k++) {
! 1710: a = ctx->bund->params.acl_filters[k];
! 1711: if (a == NULL)
! 1712: a = acl_filters[k];
! 1713: while (a) {
! 1714: Printf("\t%d#%d\t: '%s'\r\n", (k + 1), a->number, a->rule);
! 1715: a = a->next;
! 1716: }
! 1717: }
! 1718: Printf("Traffic limits:\r\n");
! 1719: for (k = 0; k < 2; k++) {
! 1720: a = ctx->bund->params.acl_limits[k];
! 1721: while (a) {
! 1722: Printf("\t%s#%d%s%s\t: '%s'\r\n", (k?"out":"in"), a->number,
! 1723: ((a->name[0])?"#":""), a->name, a->rule);
! 1724: a = a->next;
! 1725: }
! 1726: }
! 1727: #endif /* USE_NG_BPF */
! 1728: }
! 1729: return(0);
! 1730: }
! 1731:
! 1732: /*
! 1733: * IfaceSetMTU()
! 1734: *
! 1735: * Set MTU and bandwidth on bundle's interface
! 1736: */
! 1737:
! 1738: void
! 1739: IfaceSetMTU(Bund b, int mtu)
! 1740: {
! 1741: IfaceState const iface = &b->iface;
! 1742: struct ifreq ifr;
! 1743: int s;
! 1744:
! 1745: /* Get socket */
! 1746: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 1747: Perror("[%s] IFACE: Can't get socket to set MTU", b->name);
! 1748: return;
! 1749: }
! 1750:
! 1751: if ((b->params.mtu > 0) && (mtu > b->params.mtu)) {
! 1752: mtu = b->params.mtu;
! 1753: Log(LG_IFACE2, ("[%s] IFACE: forcing MTU of auth backend: %d bytes",
! 1754: b->name, mtu));
! 1755: }
! 1756:
! 1757: /* Limit MTU to configured maximum */
! 1758: if (mtu > iface->max_mtu)
! 1759: mtu = iface->max_mtu;
! 1760:
! 1761: /* Set MTU on interface */
! 1762: memset(&ifr, 0, sizeof(ifr));
! 1763: strlcpy(ifr.ifr_name, b->iface.ifname, sizeof(ifr.ifr_name));
! 1764: ifr.ifr_mtu = mtu;
! 1765: Log(LG_IFACE2, ("[%s] IFACE: setting %s MTU to %d bytes",
! 1766: b->name, b->iface.ifname, mtu));
! 1767: if (ioctl(s, SIOCSIFMTU, (char *)&ifr) < 0)
! 1768: Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCSIFMTU");
! 1769: close(s);
! 1770:
! 1771: /* Save MTU */
! 1772: iface->mtu = mtu;
! 1773:
! 1774: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 1775: /* Update tcpmssfix config */
! 1776: if (iface->mss_up)
! 1777: IfaceSetupMSS(b, MAXMSS(mtu));
! 1778: #endif
! 1779:
! 1780: }
! 1781:
! 1782: void
! 1783: IfaceChangeFlags(Bund b, int clear, int set)
! 1784: {
! 1785: struct ifreq ifrq;
! 1786: int s, new_flags;
! 1787:
! 1788: Log(LG_IFACE2, ("[%s] IFACE: Change interface flags: -%d +%d",
! 1789: b->name, clear, set));
! 1790:
! 1791: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 1792: Perror("[%s] IFACE: Can't get socket to change interface flags", b->name);
! 1793: return;
! 1794: }
! 1795:
! 1796: memset(&ifrq, '\0', sizeof(ifrq));
! 1797: strlcpy(ifrq.ifr_name, b->iface.ifname, sizeof(ifrq.ifr_name));
! 1798: ifrq.ifr_name[sizeof(ifrq.ifr_name) - 1] = '\0';
! 1799: if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
! 1800: Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCGIFFLAGS");
! 1801: close(s);
! 1802: return;
! 1803: }
! 1804: new_flags = (ifrq.ifr_flags & 0xffff) | (ifrq.ifr_flagshigh << 16);
! 1805:
! 1806: new_flags &= ~clear;
! 1807: new_flags |= set;
! 1808:
! 1809: ifrq.ifr_flags = new_flags & 0xffff;
! 1810: ifrq.ifr_flagshigh = new_flags >> 16;
! 1811:
! 1812: if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
! 1813: Perror("[%s] IFACE: ioctl(%s, %s)", b->name, b->iface.ifname, "SIOCSIFFLAGS");
! 1814: close(s);
! 1815: return;
! 1816: }
! 1817: close(s);
! 1818: }
! 1819:
! 1820: #if defined(__KAME__) && !defined(NOINET6)
! 1821: static void
! 1822: add_scope(struct sockaddr *sa, int ifindex)
! 1823: {
! 1824: struct sockaddr_in6 *sa6;
! 1825:
! 1826: if (sa->sa_family != AF_INET6)
! 1827: return;
! 1828: sa6 = (struct sockaddr_in6 *)sa;
! 1829: if (!IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) &&
! 1830: !IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr))
! 1831: return;
! 1832: if (*(u_int16_t *)&sa6->sin6_addr.s6_addr[2] != 0)
! 1833: return;
! 1834: *(u_int16_t *)&sa6->sin6_addr.s6_addr[2] = htons(ifindex);
! 1835: }
! 1836: #endif
! 1837:
! 1838: int
! 1839: IfaceChangeAddr(Bund b, int add, struct u_range *self, struct u_addr *peer)
! 1840: {
! 1841: struct ifaliasreq ifra;
! 1842: struct in6_aliasreq ifra6;
! 1843: struct sockaddr_in *me4, *msk4, *peer4;
! 1844: struct sockaddr_storage ssself, sspeer, ssmsk;
! 1845: int res = 0;
! 1846: int s;
! 1847: char buf[48], buf1[48];
! 1848:
! 1849: Log(LG_IFACE2, ("[%s] IFACE: %s address %s->%s %s %s",
! 1850: b->name, add?"Add":"Remove", u_rangetoa(self, buf, sizeof(buf)),
! 1851: ((peer != NULL)?u_addrtoa(peer, buf1, sizeof(buf1)):""),
! 1852: add?"to":"from", b->iface.ifname));
! 1853:
! 1854: u_rangetosockaddrs(self, &ssself, &ssmsk);
! 1855: if (peer)
! 1856: u_addrtosockaddr(peer, 0, &sspeer);
! 1857:
! 1858: if ((s = socket(self->addr.family, SOCK_DGRAM, 0)) < 0) {
! 1859: Perror("[%s] IFACE: Can't get socket to change interface address", b->name);
! 1860: return (s);
! 1861: }
! 1862:
! 1863: switch (self->addr.family) {
! 1864: case AF_INET:
! 1865: memset(&ifra, '\0', sizeof(ifra));
! 1866: strlcpy(ifra.ifra_name, b->iface.ifname, sizeof(ifra.ifra_name));
! 1867:
! 1868: me4 = (struct sockaddr_in *)&ifra.ifra_addr;
! 1869: memcpy(me4, &ssself, sizeof(*me4));
! 1870:
! 1871: msk4 = (struct sockaddr_in *)&ifra.ifra_mask;
! 1872: memcpy(msk4, &ssmsk, sizeof(*msk4));
! 1873:
! 1874: peer4 = (struct sockaddr_in *)&ifra.ifra_broadaddr;
! 1875: if (peer == NULL || peer->family == AF_UNSPEC) {
! 1876: peer4->sin_family = AF_INET;
! 1877: peer4->sin_len = sizeof(*peer4);
! 1878: peer4->sin_addr.s_addr = INADDR_NONE;
! 1879: } else
! 1880: memcpy(peer4, &sspeer, sizeof(*peer4));
! 1881:
! 1882: res = ioctl(s, add?SIOCAIFADDR:SIOCDIFADDR, &ifra);
! 1883: if (res == -1) {
! 1884: Perror("[%s] IFACE: %s IPv4 address %s %s failed",
! 1885: b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname);
! 1886: }
! 1887: break;
! 1888:
! 1889: case AF_INET6:
! 1890: memset(&ifra6, '\0', sizeof(ifra6));
! 1891: strlcpy(ifra6.ifra_name, b->iface.ifname, sizeof(ifra6.ifra_name));
! 1892:
! 1893: memcpy(&ifra6.ifra_addr, &ssself, sizeof(ifra6.ifra_addr));
! 1894: memcpy(&ifra6.ifra_prefixmask, &ssmsk, sizeof(ifra6.ifra_prefixmask));
! 1895: if (peer == NULL || peer->family == AF_UNSPEC)
! 1896: ifra6.ifra_dstaddr.sin6_family = AF_UNSPEC;
! 1897: else if (memcmp(&((struct sockaddr_in6 *)&ssmsk)->sin6_addr, &in6mask128,
! 1898: sizeof(in6mask128)) == 0)
! 1899: memcpy(&ifra6.ifra_dstaddr, &sspeer, sizeof(ifra6.ifra_dstaddr));
! 1900: ifra6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
! 1901: ifra6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
! 1902:
! 1903: res = ioctl(s, add?SIOCAIFADDR_IN6:SIOCDIFADDR_IN6, &ifra6);
! 1904: if (res == -1) {
! 1905: Perror("[%s] IFACE: %s IPv6 address %s %s failed",
! 1906: b->name, add?"Adding":"Removing", add?"to":"from", b->iface.ifname);
! 1907: }
! 1908: break;
! 1909:
! 1910: default:
! 1911: res = -1;
! 1912: break;
! 1913: }
! 1914: close(s);
! 1915: return (res);
! 1916: }
! 1917:
! 1918: struct rtmsg {
! 1919: struct rt_msghdr m_rtm;
! 1920: char m_space[256];
! 1921: };
! 1922:
! 1923: static size_t
! 1924: memcpy_roundup(char *cp, const void *data, size_t len)
! 1925: {
! 1926: size_t padlen;
! 1927:
! 1928: #define ROUNDUP(x) ((x) ? (1 + (((x) - 1) | (sizeof(long) - 1))) : sizeof(long))
! 1929: padlen = ROUNDUP(len);
! 1930: memcpy(cp, data, len);
! 1931: if (padlen > len)
! 1932: memset(cp + len, '\0', padlen - len);
! 1933:
! 1934: return padlen;
! 1935: }
! 1936:
! 1937: int
! 1938: IfaceSetRoute(Bund b, int cmd, struct u_range *dst,
! 1939: struct u_addr *gw)
! 1940: {
! 1941: struct rtmsg rtmes;
! 1942: int s, nb, wb;
! 1943: char *cp;
! 1944: const char *cmdstr = (cmd == RTM_ADD ? "Add" : "Delete");
! 1945: struct sockaddr_storage sadst, samask, sagw;
! 1946: char buf[48], buf1[48];
! 1947:
! 1948: s = socket(PF_ROUTE, SOCK_RAW, 0);
! 1949: if (s < 0) {
! 1950: Perror("[%s] IFACE: Can't get route socket", b->name);
! 1951: return (-1);
! 1952: }
! 1953: memset(&rtmes, '\0', sizeof(rtmes));
! 1954: rtmes.m_rtm.rtm_version = RTM_VERSION;
! 1955: rtmes.m_rtm.rtm_type = cmd;
! 1956: rtmes.m_rtm.rtm_addrs = RTA_DST;
! 1957: rtmes.m_rtm.rtm_seq = ++gRouteSeq;
! 1958: rtmes.m_rtm.rtm_pid = gPid;
! 1959: rtmes.m_rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
! 1960:
! 1961: u_rangetosockaddrs(dst, &sadst, &samask);
! 1962: #if defined(__KAME__) && !defined(NOINET6)
! 1963: add_scope((struct sockaddr *)&sadst, b->iface.ifindex);
! 1964: #endif
! 1965:
! 1966: cp = rtmes.m_space;
! 1967: cp += memcpy_roundup(cp, &sadst, sadst.ss_len);
! 1968: if (gw != NULL) {
! 1969: u_addrtosockaddr(gw, 0, &sagw);
! 1970: #if defined(__KAME__) && !defined(NOINET6)
! 1971: add_scope((struct sockaddr *)&sagw, b->iface.ifindex);
! 1972: #endif
! 1973: cp += memcpy_roundup(cp, &sagw, sagw.ss_len);
! 1974: rtmes.m_rtm.rtm_addrs |= RTA_GATEWAY;
! 1975: } else if (cmd == RTM_ADD) {
! 1976: Log(LG_ERR, ("[%s] IfaceSetRoute: gw is not set\n", b->name));
! 1977: close(s);
! 1978: return (-1);
! 1979: }
! 1980:
! 1981: if (u_rangehost(dst)) {
! 1982: rtmes.m_rtm.rtm_flags |= RTF_HOST;
! 1983: } else {
! 1984: cp += memcpy_roundup(cp, &samask, samask.ss_len);
! 1985: rtmes.m_rtm.rtm_addrs |= RTA_NETMASK;
! 1986: }
! 1987:
! 1988: nb = cp - (char *)&rtmes;
! 1989: rtmes.m_rtm.rtm_msglen = nb;
! 1990: wb = write(s, &rtmes, nb);
! 1991: if (wb < 0) {
! 1992: Log(LG_ERR, ("[%s] IFACE: %s route %s %s failed: %s",
! 1993: b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)),
! 1994: ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):""),
! 1995: (rtmes.m_rtm.rtm_errno != 0)?strerror(rtmes.m_rtm.rtm_errno):strerror(errno)));
! 1996: close(s);
! 1997: return (-1);
! 1998: }
! 1999: close(s);
! 2000: Log(LG_IFACE2, ("[%s] IFACE: %s route %s %s",
! 2001: b->name, cmdstr, u_rangetoa(dst, buf, sizeof(buf)),
! 2002: ((gw != NULL)?u_addrtoa(gw, buf1, sizeof(buf1)):"")));
! 2003: return (0);
! 2004: }
! 2005:
! 2006: #ifndef USE_NG_TCPMSS
! 2007: void
! 2008: IfaceCorrectMSS(Mbuf pkt, uint16_t maxmss)
! 2009: {
! 2010: struct ip *iphdr;
! 2011: struct tcphdr *tc;
! 2012: int pktlen, hlen, olen, optlen, accumulate;
! 2013: uint16_t *mss;
! 2014: u_char *opt;
! 2015:
! 2016: if (pkt == NULL)
! 2017: return;
! 2018:
! 2019: iphdr = (struct ip *)MBDATAU(pkt);
! 2020: hlen = iphdr->ip_hl << 2;
! 2021: pktlen = MBLEN(pkt) - hlen;
! 2022: tc = (struct tcphdr *)(MBDATAU(pkt) + hlen);
! 2023: hlen = tc->th_off << 2;
! 2024:
! 2025: /* Invalid header length or header without options. */
! 2026: if (hlen <= sizeof(struct tcphdr) || hlen > pktlen)
! 2027: return;
! 2028:
! 2029: /* MSS option only allowed within SYN packets. */
! 2030: if (!(tc->th_flags & TH_SYN))
! 2031: return;
! 2032:
! 2033: for (olen = hlen - sizeof(struct tcphdr), opt = (u_char *)(tc + 1);
! 2034: olen > 0; olen -= optlen, opt += optlen) {
! 2035: if (*opt == TCPOPT_EOL)
! 2036: break;
! 2037: else if (*opt == TCPOPT_NOP)
! 2038: optlen = 1;
! 2039: else {
! 2040: optlen = *(opt + 1);
! 2041: if (optlen <= 0 || optlen > olen)
! 2042: break;
! 2043: if (*opt == TCPOPT_MAXSEG) {
! 2044: if (optlen != TCPOLEN_MAXSEG)
! 2045: continue;
! 2046: mss = (u_int16_t *)(opt + 2);
! 2047: if (ntohs(*mss) > maxmss) {
! 2048: accumulate = *mss;
! 2049: *mss = htons(maxmss);
! 2050: accumulate -= *mss;
! 2051: ADJUST_CHECKSUM(accumulate, tc->th_sum);
! 2052: }
! 2053: }
! 2054: }
! 2055: }
! 2056: }
! 2057: #endif
! 2058:
! 2059: static int
! 2060: IfaceNgIpInit(Bund b, int ready)
! 2061: {
! 2062: struct ngm_connect cn;
! 2063: char path[NG_PATHSIZ];
! 2064: char hook[NG_HOOKSIZ];
! 2065:
! 2066: if (!ready) {
! 2067: /* Dial-on-Demand mode */
! 2068: /* Use demand hook of the socket node */
! 2069: snprintf(path, sizeof(path), ".:");
! 2070: snprintf(hook, sizeof(hook), "4%d", b->id);
! 2071:
! 2072: } else {
! 2073:
! 2074: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 2075: strcpy(hook, NG_PPP_HOOK_INET);
! 2076:
! 2077: #ifdef USE_NG_NAT
! 2078: /* Add a nat node if configured */
! 2079: if (Enabled(&b->iface.options, IFACE_CONF_NAT)) {
! 2080: if (IfaceInitNAT(b, path, hook))
! 2081: goto fail;
! 2082: b->iface.nat_up = 1;
! 2083: }
! 2084: #endif
! 2085:
! 2086: /* Add a tee node if configured */
! 2087: if (Enabled(&b->iface.options, IFACE_CONF_TEE)) {
! 2088: if (IfaceInitTee(b, path, hook, 0))
! 2089: goto fail;
! 2090: b->iface.tee_up = 1;
! 2091: }
! 2092:
! 2093: #ifdef USE_NG_IPACCT
! 2094: /* Connect a ipacct node if configured */
! 2095: if (Enabled(&b->iface.options, IFACE_CONF_IPACCT)) {
! 2096: if (IfaceInitIpacct(b, path, hook))
! 2097: goto fail;
! 2098: b->iface.ipacct_up = 1;
! 2099: }
! 2100: #endif /* USE_NG_IPACCT */
! 2101:
! 2102: #ifdef USE_NG_NETFLOW
! 2103: #ifdef NG_NETFLOW_CONF_INGRESS
! 2104: /* Connect a netflow node if configured */
! 2105: if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN) ||
! 2106: Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) {
! 2107: if (IfaceInitNetflow(b, path, hook,
! 2108: Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)?1:0,
! 2109: Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)?1:0))
! 2110: goto fail;
! 2111: if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN))
! 2112: b->iface.nfin_up = 1;
! 2113: if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT))
! 2114: b->iface.nfout_up = 1;
! 2115: }
! 2116: #else /* NG_NETFLOW_CONF_INGRESS */
! 2117: /* Connect a netflow node if configured */
! 2118: if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_IN)) {
! 2119: if (IfaceInitNetflow(b, path, hook, 1, 0))
! 2120: goto fail;
! 2121: b->iface.nfin_up = 1;
! 2122: }
! 2123:
! 2124: if (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_OUT)) {
! 2125: if (IfaceInitNetflow(b, path, hook, 0, 1))
! 2126: goto fail;
! 2127: b->iface.nfout_up = 1;
! 2128: }
! 2129: #endif /* NG_NETFLOW_CONF_INGRESS */
! 2130: #endif /* USE_NG_NETFLOW */
! 2131:
! 2132: }
! 2133:
! 2134: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 2135: if (Enabled(&b->iface.options, IFACE_CONF_TCPMSSFIX)) {
! 2136: if (IfaceInitMSS(b, path, hook))
! 2137: goto fail;
! 2138: b->iface.mss_up = 1;
! 2139: }
! 2140: #endif
! 2141:
! 2142: #ifdef USE_NG_BPF
! 2143: if (IfaceInitLimits(b, path, hook))
! 2144: goto fail;
! 2145: #endif
! 2146:
! 2147: /* Connect graph to the iface node. */
! 2148: memset(&cn, 0, sizeof(cn));
! 2149: strcpy(cn.ourhook, hook);
! 2150: snprintf(cn.path, sizeof(cn.path), "%s:", b->iface.ngname);
! 2151: strcpy(cn.peerhook, NG_IFACE_HOOK_INET);
! 2152: if (NgSendMsg(gLinksCsock, path,
! 2153: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 2154: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2155: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2156: goto fail;
! 2157: }
! 2158:
! 2159: if (ready) {
! 2160: #ifdef USE_NG_NETFLOW
! 2161: #ifdef NG_NETFLOW_CONF_INGRESS
! 2162: if (b->iface.nfin_up || b->iface.nfout_up)
! 2163: IfaceSetupNetflow(b, b->iface.nfin_up, b->iface.nfout_up);
! 2164: #else /* NG_NETFLOW_CONF_INGRESS */
! 2165: if (b->iface.nfin_up)
! 2166: IfaceSetupNetflow(b, 1, 0);
! 2167:
! 2168: if (b->iface.nfout_up)
! 2169: IfaceSetupNetflow(b, 0, 1);
! 2170: #endif /* NG_NETFLOW_CONF_INGRESS */
! 2171: #endif /* USE_NG_NETFLOW */
! 2172: }
! 2173:
! 2174: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 2175: if (b->iface.mss_up)
! 2176: IfaceSetupMSS(b, MAXMSS(b->iface.mtu));
! 2177: #endif
! 2178:
! 2179: #ifdef USE_NG_BPF
! 2180: IfaceSetupLimits(b);
! 2181: #endif
! 2182:
! 2183: /* OK */
! 2184: return(0);
! 2185:
! 2186: fail:
! 2187: return(-1);
! 2188: }
! 2189:
! 2190: /*
! 2191: * IfaceNgIpShutdown()
! 2192: */
! 2193:
! 2194: static void
! 2195: IfaceNgIpShutdown(Bund b)
! 2196: {
! 2197: char path[NG_PATHSIZ];
! 2198:
! 2199: #ifdef USE_NG_BPF
! 2200: IfaceShutdownLimits(b); /* Limits must shutdown first to save final stats. */
! 2201: #endif
! 2202: #ifdef USE_NG_NAT
! 2203: if (b->iface.nat_up)
! 2204: IfaceShutdownNAT(b);
! 2205: b->iface.nat_up = 0;
! 2206: #endif
! 2207: if (b->iface.tee_up)
! 2208: IfaceShutdownTee(b, 0);
! 2209: b->iface.tee_up = 0;
! 2210: #ifdef USE_NG_NETFLOW
! 2211: #ifdef NG_NETFLOW_CONF_INGRESS
! 2212: if (b->iface.nfin_up || b->iface.nfout_up)
! 2213: IfaceShutdownNetflow(b, b->iface.nfin_up, b->iface.nfout_up);
! 2214: b->iface.nfin_up = 0;
! 2215: b->iface.nfout_up = 0;
! 2216: #else /* NG_NETFLOW_CONF_INGRESS */
! 2217: if (b->iface.nfin_up)
! 2218: IfaceShutdownNetflow(b, 1, 0);
! 2219: b->iface.nfin_up = 0;
! 2220: if (b->iface.nfout_up)
! 2221: IfaceShutdownNetflow(b, 0, 1);
! 2222: b->iface.nfout_up = 0;
! 2223: #endif /* NG_NETFLOW_CONF_INGRESS */
! 2224: #endif
! 2225: #ifdef USE_NG_IPACCT
! 2226: if (b->iface.ipacct_up)
! 2227: IfaceShutdownIpacct(b);
! 2228: b->iface.ipacct_up = 0;
! 2229: #endif
! 2230: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 2231: if (b->iface.mss_up)
! 2232: IfaceShutdownMSS(b);
! 2233: #endif
! 2234: b->iface.mss_up = 0;
! 2235:
! 2236: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 2237: NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_INET);
! 2238:
! 2239: snprintf(path, sizeof(path), "%s:", b->iface.ngname);
! 2240: NgFuncDisconnect(gLinksCsock, b->name, path, NG_IFACE_HOOK_INET);
! 2241: }
! 2242:
! 2243: static int
! 2244: IfaceNgIpv6Init(Bund b, int ready)
! 2245: {
! 2246: struct ngm_connect cn;
! 2247: char path[NG_PATHSIZ];
! 2248: char hook[NG_HOOKSIZ];
! 2249:
! 2250: if (!ready) {
! 2251: /* Dial-on-Demand mode */
! 2252: /* Use demand hook of the socket node */
! 2253: snprintf(path, sizeof(path), ".:");
! 2254: snprintf(hook, sizeof(hook), "6%d", b->id);
! 2255: } else {
! 2256: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 2257: strcpy(hook, NG_PPP_HOOK_IPV6);
! 2258:
! 2259: /* Add a tee node if configured */
! 2260: if (Enabled(&b->iface.options, IFACE_CONF_TEE)) {
! 2261: if (IfaceInitTee(b, path, hook, 1))
! 2262: goto fail;
! 2263: b->iface.tee6_up = 1;
! 2264: }
! 2265:
! 2266: }
! 2267:
! 2268: /* Connect graph to the iface node. */
! 2269: strcpy(cn.ourhook, hook);
! 2270: snprintf(cn.path, sizeof(cn.path), "%s:", b->iface.ngname);
! 2271: strcpy(cn.peerhook, NG_IFACE_HOOK_INET6);
! 2272: if (NgSendMsg(gLinksCsock, path,
! 2273: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 2274: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2275: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2276: goto fail;
! 2277: }
! 2278:
! 2279: /* OK */
! 2280: return(0);
! 2281:
! 2282: fail:
! 2283: return(-1);
! 2284: }
! 2285:
! 2286: /*
! 2287: * IfaceNgIpv6Shutdown()
! 2288: */
! 2289:
! 2290: static void
! 2291: IfaceNgIpv6Shutdown(Bund b)
! 2292: {
! 2293: char path[NG_PATHSIZ];
! 2294:
! 2295: if (b->iface.tee6_up)
! 2296: IfaceShutdownTee(b, 1);
! 2297: b->iface.tee6_up = 0;
! 2298:
! 2299: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 2300: NgFuncDisconnect(gLinksCsock, b->name, path, NG_PPP_HOOK_IPV6);
! 2301:
! 2302: snprintf(path, sizeof(path), "%s:", b->iface.ngname);
! 2303: NgFuncDisconnect(gLinksCsock, b->name, path, NG_IFACE_HOOK_INET6);
! 2304: }
! 2305:
! 2306: #ifdef USE_NG_NAT
! 2307: static int
! 2308: IfaceInitNAT(Bund b, char *path, char *hook)
! 2309: {
! 2310: NatState const nat = &b->iface.nat;
! 2311: struct ngm_mkpeer mp;
! 2312: struct ngm_name nm;
! 2313: struct in_addr ip;
! 2314: #ifdef NG_NAT_LOG
! 2315: struct ng_nat_mode mode;
! 2316: #endif
! 2317: Log(LG_IFACE2, ("[%s] IFACE: Connecting NAT", b->name));
! 2318:
! 2319: strcpy(mp.type, NG_NAT_NODE_TYPE);
! 2320: strcpy(mp.ourhook, hook);
! 2321: strcpy(mp.peerhook, NG_NAT_HOOK_IN);
! 2322: if (NgSendMsg(gLinksCsock, path,
! 2323: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2324: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
! 2325: b->name, NG_NAT_NODE_TYPE, path, mp.ourhook);
! 2326: return(-1);
! 2327: }
! 2328: strlcat(path, ".", NG_PATHSIZ);
! 2329: strlcat(path, hook, NG_PATHSIZ);
! 2330: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-nat", gPid, b->name);
! 2331: if (NgSendMsg(gLinksCsock, path,
! 2332: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2333: Perror("[%s] can't name %s node", b->name, NG_NAT_NODE_TYPE);
! 2334: return(-1);
! 2335: }
! 2336: strcpy(hook, NG_NAT_HOOK_OUT);
! 2337:
! 2338: /* Set NAT IP */
! 2339: if (u_addrempty(&nat->alias_addr)) {
! 2340: ip.s_addr = 1; // Set something just to make it ready
! 2341: } else {
! 2342: ip = nat->alias_addr.u.ip4;
! 2343: }
! 2344: if (NgSendMsg(gLinksCsock, path,
! 2345: NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR, &ip, sizeof(ip)) < 0)
! 2346: Perror("[%s] can't set NAT ip", b->name);
! 2347:
! 2348: #ifdef NG_NAT_LOG
! 2349: /* Set NAT mode */
! 2350: mode.flags = 0;
! 2351: if (Enabled(&nat->options, NAT_CONF_LOG))
! 2352: mode.flags |= NG_NAT_LOG;
! 2353: if (!Enabled(&nat->options, NAT_CONF_INCOMING))
! 2354: mode.flags |= NG_NAT_DENY_INCOMING;
! 2355: if (Enabled(&nat->options, NAT_CONF_SAME_PORTS))
! 2356: mode.flags |= NG_NAT_SAME_PORTS;
! 2357: if (Enabled(&nat->options, NAT_CONF_UNREG_ONLY))
! 2358: mode.flags |= NG_NAT_UNREGISTERED_ONLY;
! 2359:
! 2360: mode.mask = NG_NAT_LOG | NG_NAT_DENY_INCOMING |
! 2361: NG_NAT_SAME_PORTS | NG_NAT_UNREGISTERED_ONLY;
! 2362: if (NgSendMsg(gLinksCsock, path,
! 2363: NGM_NAT_COOKIE, NGM_NAT_SET_MODE, &mode, sizeof(mode)) < 0)
! 2364: Perror("[%s] can't set NAT mode", b->name);
! 2365:
! 2366: /* Set NAT target IP */
! 2367: if (!u_addrempty(&nat->target_addr)) {
! 2368: ip = nat->target_addr.u.ip4;
! 2369: if (NgSendMsg(gLinksCsock, path,
! 2370: NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR, &ip, sizeof(ip)) < 0) {
! 2371: Perror("[%s] can't set NAT target IP", b->name);
! 2372: }
! 2373: }
! 2374: #endif
! 2375:
! 2376: return(0);
! 2377: }
! 2378:
! 2379: static int
! 2380: IfaceSetupNAT(Bund b)
! 2381: {
! 2382: NatState const nat = &b->iface.nat;
! 2383: char path[NG_PATHSIZ];
! 2384: int k;
! 2385:
! 2386: if (u_addrempty(&nat->alias_addr)) {
! 2387: snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name);
! 2388: if (NgSendMsg(gLinksCsock, path,
! 2389: NGM_NAT_COOKIE, NGM_NAT_SET_IPADDR,
! 2390: &b->iface.self_addr.addr.u.ip4,
! 2391: sizeof(b->iface.self_addr.addr.u.ip4)) < 0) {
! 2392: Perror("[%s] can't set NAT ip", b->name);
! 2393: return (-1);
! 2394: }
! 2395: }
! 2396: #ifdef NG_NAT_DESC_LENGTH
! 2397: /* redirect-port */
! 2398: for(k = 0; k < NM_PORT; k++) {
! 2399: if(nat->nrpt_id[k]) {
! 2400: if (NgSendMsg(gLinksCsock, path,
! 2401: NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PORT, &nat->nrpt[k],
! 2402: sizeof(struct ng_nat_redirect_port)) < 0) {
! 2403: Perror("[%s] can't set NAT redirect-port", b->name);
! 2404: }
! 2405: }
! 2406: }
! 2407: /* redirect-addr */
! 2408: for(k = 0; k < NM_ADDR; k++) {
! 2409: if(nat->nrad_id[k]) {
! 2410: if (NgSendMsg(gLinksCsock, path,
! 2411: NGM_NAT_COOKIE, NGM_NAT_REDIRECT_ADDR, &nat->nrad[k],
! 2412: sizeof(struct ng_nat_redirect_addr)) < 0) {
! 2413: Perror("[%s] can't set NAT redirect-addr", b->name);
! 2414: }
! 2415: }
! 2416: }
! 2417: /* redirect-proto */
! 2418: for(k = 0; k < NM_PROTO; k++) {
! 2419: if(nat->nrpr_id[k]) {
! 2420: if (NgSendMsg(gLinksCsock, path,
! 2421: NGM_NAT_COOKIE, NGM_NAT_REDIRECT_PROTO, &nat->nrpr[k],
! 2422: sizeof(struct ng_nat_redirect_proto)) < 0) {
! 2423: Perror("[%s] can't set NAT redirect-proto", b->name);
! 2424: }
! 2425: }
! 2426: }
! 2427: #endif
! 2428: return (0);
! 2429: }
! 2430:
! 2431: static void
! 2432: IfaceShutdownNAT(Bund b)
! 2433: {
! 2434: char path[NG_PATHSIZ];
! 2435:
! 2436: snprintf(path, sizeof(path), "mpd%d-%s-nat:", gPid, b->name);
! 2437: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 2438: }
! 2439: #endif /* USE_NG_NAT */
! 2440:
! 2441: static int
! 2442: IfaceInitTee(Bund b, char *path, char *hook, int v6)
! 2443: {
! 2444: struct ngm_mkpeer mp;
! 2445: struct ngm_name nm;
! 2446:
! 2447: Log(LG_IFACE2, ("[%s] IFACE: Connecting tee%s", b->name, v6?"6":""));
! 2448:
! 2449: strcpy(mp.type, NG_TEE_NODE_TYPE);
! 2450: strcpy(mp.ourhook, hook);
! 2451: strcpy(mp.peerhook, NG_TEE_HOOK_RIGHT);
! 2452: if (NgSendMsg(gLinksCsock, path,
! 2453: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2454: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
! 2455: b->name, NG_TEE_NODE_TYPE, path, mp.ourhook);
! 2456: return(-1);
! 2457: }
! 2458: strlcat(path, ".", NG_PATHSIZ);
! 2459: strlcat(path, hook, NG_PATHSIZ);
! 2460: snprintf(nm.name, sizeof(nm.name), "%s-tee%s", b->iface.ifname, v6?"6":"");
! 2461: if (NgSendMsg(gLinksCsock, path,
! 2462: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2463: Perror("[%s] can't name %s node", b->name, NG_TEE_NODE_TYPE);
! 2464: return(-1);
! 2465: }
! 2466: strcpy(hook, NG_TEE_HOOK_LEFT);
! 2467:
! 2468: return(0);
! 2469: }
! 2470:
! 2471: static void
! 2472: IfaceShutdownTee(Bund b, int v6)
! 2473: {
! 2474: char path[NG_PATHSIZ];
! 2475:
! 2476: snprintf(path, sizeof(path), "%s-tee%s:", b->iface.ifname, v6?"6":"");
! 2477: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 2478: }
! 2479:
! 2480: #ifdef USE_NG_IPACCT
! 2481: static int
! 2482: IfaceInitIpacct(Bund b, char *path, char *hook)
! 2483: {
! 2484: struct ngm_mkpeer mp;
! 2485: struct ngm_name nm;
! 2486: struct ngm_connect cn;
! 2487: char path1[NG_PATHSIZ];
! 2488: struct {
! 2489: struct ng_ipacct_mesg m;
! 2490: int data;
! 2491: } ipam;
! 2492:
! 2493: Log(LG_IFACE2, ("[%s] IFACE: Connecting ipacct", b->name));
! 2494:
! 2495: strcpy(mp.type, NG_TEE_NODE_TYPE);
! 2496: strcpy(mp.ourhook, hook);
! 2497: strcpy(mp.peerhook, NG_TEE_HOOK_RIGHT);
! 2498: if (NgSendMsg(gLinksCsock, path,
! 2499: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2500: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
! 2501: b->name, NG_TEE_NODE_TYPE, path, mp.ourhook);
! 2502: return(-1);
! 2503: }
! 2504: strlcat(path, ".", NG_PATHSIZ);
! 2505: strlcat(path, hook, NG_PATHSIZ);
! 2506: snprintf(nm.name, sizeof(nm.name), "%s_acct_tee", b->iface.ifname);
! 2507: if (NgSendMsg(gLinksCsock, path,
! 2508: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2509: Perror("[%s] can't name %s node", b->name, NG_TEE_NODE_TYPE);
! 2510: return(-1);
! 2511: }
! 2512: strcpy(hook, NG_TEE_HOOK_LEFT);
! 2513:
! 2514: strcpy(mp.type, NG_IPACCT_NODE_TYPE);
! 2515: strcpy(mp.ourhook, NG_TEE_HOOK_RIGHT2LEFT);
! 2516: snprintf(mp.peerhook, sizeof(mp.peerhook), "%s_in", b->iface.ifname);
! 2517: if (NgSendMsg(gLinksCsock, path,
! 2518: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2519: Perror("[%s] can't create %s node at \"%s\"->\"%s\"",
! 2520: b->name, NG_IPACCT_NODE_TYPE, path, mp.ourhook);
! 2521: return(-1);
! 2522: }
! 2523: snprintf(path1, sizeof(path1), "%s.%s", path, NG_TEE_HOOK_RIGHT2LEFT);
! 2524: snprintf(nm.name, sizeof(nm.name), "%s_ip_acct", b->iface.ifname);
! 2525: if (NgSendMsg(gLinksCsock, path1,
! 2526: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2527: Perror("[%s] can't name %s node", b->name, NG_IPACCT_NODE_TYPE);
! 2528: return(-1);
! 2529: }
! 2530: strcpy(cn.ourhook, NG_TEE_HOOK_LEFT2RIGHT);
! 2531: strcpy(cn.path, NG_TEE_HOOK_RIGHT2LEFT);
! 2532: snprintf(cn.peerhook, sizeof(cn.peerhook), "%s_out", b->iface.ifname);
! 2533: if (NgSendMsg(gLinksCsock, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
! 2534: sizeof(cn)) < 0) {
! 2535: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2536: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2537: return (-1);
! 2538: }
! 2539:
! 2540: snprintf(ipam.m.hname, sizeof(ipam.m.hname), "%s_in", b->iface.ifname);
! 2541: ipam.data = DLT_RAW;
! 2542: if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_SETDLT,
! 2543: &ipam, sizeof(ipam)) < 0) {
! 2544: Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
! 2545: return (-1);
! 2546: }
! 2547: ipam.data = 10000;
! 2548: if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_STHRS,
! 2549: &ipam, sizeof(ipam)) < 0) {
! 2550: Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
! 2551: return (-1);
! 2552: }
! 2553:
! 2554: snprintf(ipam.m.hname, sizeof(ipam.m.hname), "%s_out", b->iface.ifname);
! 2555: ipam.data = DLT_RAW;
! 2556: if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_SETDLT,
! 2557: &ipam, sizeof(ipam)) < 0) {
! 2558: Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
! 2559: return (-1);
! 2560: }
! 2561: ipam.data = 10000;
! 2562: if (NgSendMsg(gLinksCsock, path1, NGM_IPACCT_COOKIE, NGM_IPACCT_STHRS,
! 2563: &ipam, sizeof(ipam)) < 0) {
! 2564: Perror("[%s] can't set DLT \"%s\"->\"%s\"", b->name, path, ipam.m.hname);
! 2565: return (-1);
! 2566: }
! 2567:
! 2568: return(0);
! 2569: }
! 2570:
! 2571: static void
! 2572: IfaceShutdownIpacct(Bund b)
! 2573: {
! 2574: char path[NG_PATHSIZ];
! 2575:
! 2576: snprintf(path, sizeof(path), "%s_acct_tee:", b->iface.ifname);
! 2577: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 2578: }
! 2579: #endif
! 2580:
! 2581: #ifdef USE_NG_NETFLOW
! 2582: static int
! 2583: IfaceInitNetflow(Bund b, char *path, char *hook, char in, char out)
! 2584: {
! 2585: struct ngm_connect cn;
! 2586: int nif;
! 2587:
! 2588: #ifdef NG_NETFLOW_CONF_INGRESS
! 2589: nif = gNetflowIface + b->id;
! 2590: #else
! 2591: nif = gNetflowIface + b->id*2 + out;
! 2592: #endif
! 2593:
! 2594: Log(LG_IFACE2, ("[%s] IFACE: Connecting netflow (%s)", b->name, out?"out":"in"));
! 2595:
! 2596: /* Create global ng_netflow(4) node if not yet. */
! 2597: if (gNetflowNodeID == 0) {
! 2598: if (NgFuncInitGlobalNetflow())
! 2599: return(-1);
! 2600: }
! 2601:
! 2602: /* Connect ng_netflow(4) node to the ng_bpf(4)/ng_tee(4) node. */
! 2603: strcpy(cn.ourhook, hook);
! 2604: snprintf(cn.path, sizeof(cn.path), "[%x]:", gNetflowNodeID);
! 2605: #ifndef NG_NETFLOW_CONF_INGRESS
! 2606: if (out) {
! 2607: snprintf(cn.peerhook, sizeof(cn.peerhook), "%s%d", NG_NETFLOW_HOOK_OUT,
! 2608: nif);
! 2609: } else {
! 2610: #endif
! 2611: snprintf(cn.peerhook, sizeof(cn.peerhook), "%s%d", NG_NETFLOW_HOOK_DATA,
! 2612: nif);
! 2613: #ifndef NG_NETFLOW_CONF_INGRESS
! 2614: }
! 2615: #endif
! 2616: if (NgSendMsg(gLinksCsock, path, NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
! 2617: sizeof(cn)) < 0) {
! 2618: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2619: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2620: return (-1);
! 2621: }
! 2622: strlcat(path, ".", NG_PATHSIZ);
! 2623: strlcat(path, hook, NG_PATHSIZ);
! 2624: #ifndef NG_NETFLOW_CONF_INGRESS
! 2625: if (out) {
! 2626: snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_DATA, nif);
! 2627: } else {
! 2628: #endif
! 2629: snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_OUT, nif);
! 2630: #ifndef NG_NETFLOW_CONF_INGRESS
! 2631: }
! 2632: #endif
! 2633: return (0);
! 2634: }
! 2635:
! 2636: static int
! 2637: IfaceSetupNetflow(Bund b, char in, char out)
! 2638: {
! 2639: char path[NG_PATHSIZ];
! 2640: struct ng_netflow_setdlt nf_setdlt;
! 2641: struct ng_netflow_setifindex nf_setidx;
! 2642: #ifdef NG_NETFLOW_CONF_INGRESS
! 2643: struct ng_netflow_setconfig nf_setconf;
! 2644: #endif
! 2645: int nif;
! 2646:
! 2647: #ifdef NG_NETFLOW_CONF_INGRESS
! 2648: nif = gNetflowIface + b->id;
! 2649: #else
! 2650: nif = gNetflowIface + b->id*2 + out;
! 2651: #endif
! 2652:
! 2653: /* Configure data link type and interface index. */
! 2654: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
! 2655: nf_setdlt.iface = nif;
! 2656: nf_setdlt.dlt = DLT_RAW;
! 2657: if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETDLT,
! 2658: &nf_setdlt, sizeof(nf_setdlt)) < 0) {
! 2659: Perror("[%s] can't configure data link type on %s", b->name, path);
! 2660: goto fail;
! 2661: }
! 2662: #ifdef NG_NETFLOW_CONF_INGRESS
! 2663: nf_setconf.iface = nif;
! 2664: nf_setconf.conf =
! 2665: (in?NG_NETFLOW_CONF_INGRESS:0) |
! 2666: (out?NG_NETFLOW_CONF_EGRESS:0) |
! 2667: (Enabled(&b->iface.options, IFACE_CONF_NETFLOW_ONCE)?NG_NETFLOW_CONF_ONCE:0);
! 2668: if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETCONFIG,
! 2669: &nf_setconf, sizeof(nf_setconf)) < 0) {
! 2670: Perror("[%s] can't set config on %s", b->name, path);
! 2671: goto fail;
! 2672: }
! 2673: #endif
! 2674: #ifndef NG_NETFLOW_CONF_INGRESS
! 2675: if (!out) {
! 2676: #endif
! 2677: nf_setidx.iface = nif;
! 2678: nf_setidx.index = if_nametoindex(b->iface.ifname);
! 2679: if (NgSendMsg(gLinksCsock, path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_SETIFINDEX,
! 2680: &nf_setidx, sizeof(nf_setidx)) < 0) {
! 2681: Perror("[%s] can't configure interface index on %s", b->name, path);
! 2682: goto fail;
! 2683: }
! 2684: #ifndef NG_NETFLOW_CONF_INGRESS
! 2685: }
! 2686: #endif
! 2687:
! 2688: return 0;
! 2689: fail:
! 2690: return -1;
! 2691: }
! 2692:
! 2693: static void
! 2694: IfaceShutdownNetflow(Bund b, char in, char out)
! 2695: {
! 2696: char path[NG_PATHSIZ];
! 2697: char hook[NG_HOOKSIZ];
! 2698: int nif;
! 2699:
! 2700: #ifdef NG_NETFLOW_CONF_INGRESS
! 2701: nif = gNetflowIface + b->id;
! 2702: #else
! 2703: nif = gNetflowIface + b->id*2 + out;
! 2704: #endif
! 2705:
! 2706: snprintf(path, NG_PATHSIZ, "[%x]:", gNetflowNodeID);
! 2707: snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_DATA, nif);
! 2708: NgFuncDisconnect(gLinksCsock, b->name, path, hook);
! 2709: snprintf(hook, NG_HOOKSIZ, "%s%d", NG_NETFLOW_HOOK_OUT, nif);
! 2710: NgFuncDisconnect(gLinksCsock, b->name, path, hook);
! 2711: }
! 2712: #endif
! 2713:
! 2714: #if defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF))
! 2715: static int
! 2716: IfaceInitMSS(Bund b, char *path, char *hook)
! 2717: {
! 2718: struct ngm_mkpeer mp;
! 2719: struct ngm_name nm;
! 2720: #ifndef USE_NG_TCPMSS
! 2721: struct ngm_connect cn;
! 2722: #endif
! 2723:
! 2724: Log(LG_IFACE2, ("[%s] IFACE: Connecting tcpmssfix", b->name));
! 2725:
! 2726: #ifdef USE_NG_TCPMSS
! 2727: /* Create ng_tcpmss(4) node. */
! 2728: strcpy(mp.type, NG_TCPMSS_NODE_TYPE);
! 2729: strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
! 2730: strcpy(mp.peerhook, "in");
! 2731: if (NgSendMsg(gLinksCsock, path,
! 2732: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2733: Perror("can't create %s node at \"%s\"->\"%s\"",
! 2734: NG_TCPMSS_NODE_TYPE, path, mp.ourhook);
! 2735: goto fail;
! 2736: }
! 2737:
! 2738: strlcat(path, ".", NG_PATHSIZ);
! 2739: strlcat(path, hook, NG_PATHSIZ);
! 2740: snprintf(hook, NG_HOOKSIZ, "out");
! 2741:
! 2742: /* Set the new node's name. */
! 2743: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-mss", gPid, b->name);
! 2744: if (NgSendMsg(gLinksCsock, path,
! 2745: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2746: Perror("can't name %s node", NG_TCPMSS_NODE_TYPE);
! 2747: goto fail;
! 2748: }
! 2749:
! 2750: #else
! 2751: /* Create a bpf node for SYN detection. */
! 2752: strcpy(mp.type, NG_BPF_NODE_TYPE);
! 2753: strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
! 2754: strcpy(mp.peerhook, "ppp");
! 2755: if (NgSendMsg(gLinksCsock, path,
! 2756: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2757: Perror("can't create %s node at \"%s\"->\"%s\"",
! 2758: NG_BPF_NODE_TYPE, path, mp.ourhook);
! 2759: goto fail;
! 2760: }
! 2761:
! 2762: strlcat(path, ".", NG_PATHSIZ);
! 2763: strlcat(path, hook, NG_PATHSIZ);
! 2764: strcpy(hook, "iface");
! 2765:
! 2766: /* Set the new node's name. */
! 2767: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-mss", gPid, b->name);
! 2768: if (NgSendMsg(gLinksCsock, path,
! 2769: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2770: Perror("can't name tcpmssfix %s node", NG_BPF_NODE_TYPE);
! 2771: goto fail;
! 2772: }
! 2773:
! 2774: /* Connect to the bundle socket node. */
! 2775: strlcpy(cn.path, path, sizeof(cn.path));
! 2776: snprintf(cn.ourhook, sizeof(cn.ourhook), "i%d", b->id);
! 2777: strcpy(cn.peerhook, MPD_HOOK_TCPMSS_IN);
! 2778: if (NgSendMsg(gLinksCsock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
! 2779: sizeof(cn)) < 0) {
! 2780: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2781: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2782: goto fail;
! 2783: }
! 2784:
! 2785: strlcpy(cn.path, path, sizeof(cn.path));
! 2786: snprintf(cn.ourhook, sizeof(cn.ourhook), "o%d", b->id);
! 2787: strcpy(cn.peerhook, MPD_HOOK_TCPMSS_OUT);
! 2788: if (NgSendMsg(gLinksCsock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
! 2789: sizeof(cn)) < 0) {
! 2790: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 2791: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 2792: goto fail;
! 2793: }
! 2794: #endif /* USE_NG_TCPMSS */
! 2795:
! 2796: return (0);
! 2797: fail:
! 2798: return (-1);
! 2799: }
! 2800:
! 2801: /*
! 2802: * BundConfigMSS()
! 2803: *
! 2804: * Configure the tcpmss node to reduce MSS to given value.
! 2805: */
! 2806:
! 2807: static void
! 2808: IfaceSetupMSS(Bund b, uint16_t maxMSS)
! 2809: {
! 2810: #ifdef USE_NG_TCPMSS
! 2811: struct ng_tcpmss_config tcpmsscfg;
! 2812: char path[NG_PATHSIZ];
! 2813:
! 2814: snprintf(path, sizeof(path), "mpd%d-%s-mss:", gPid, b->name);
! 2815:
! 2816: /* Send configure message. */
! 2817: memset(&tcpmsscfg, 0, sizeof(tcpmsscfg));
! 2818: tcpmsscfg.maxMSS = maxMSS;
! 2819:
! 2820: snprintf(tcpmsscfg.inHook, sizeof(tcpmsscfg.inHook), "in");
! 2821: snprintf(tcpmsscfg.outHook, sizeof(tcpmsscfg.outHook), "out");
! 2822: if (NgSendMsg(gLinksCsock, path, NGM_TCPMSS_COOKIE, NGM_TCPMSS_CONFIG,
! 2823: &tcpmsscfg, sizeof(tcpmsscfg)) < 0) {
! 2824: Perror("[%s] can't configure %s node program", b->name, NG_TCPMSS_NODE_TYPE);
! 2825: }
! 2826: snprintf(tcpmsscfg.inHook, sizeof(tcpmsscfg.inHook), "out");
! 2827: snprintf(tcpmsscfg.outHook, sizeof(tcpmsscfg.outHook), "in");
! 2828: if (NgSendMsg(gLinksCsock, path, NGM_TCPMSS_COOKIE, NGM_TCPMSS_CONFIG,
! 2829: &tcpmsscfg, sizeof(tcpmsscfg)) < 0) {
! 2830: Perror("[%s] can't configure %s node program", b->name, NG_TCPMSS_NODE_TYPE);
! 2831: }
! 2832: #else
! 2833: union {
! 2834: u_char buf[NG_BPF_HOOKPROG_SIZE(TCPSYN_PROG_LEN)];
! 2835: struct ng_bpf_hookprog hprog;
! 2836: } u;
! 2837: struct ng_bpf_hookprog *const hp = &u.hprog;
! 2838: char hook[NG_HOOKSIZ];
! 2839:
! 2840: /* Setup programs for ng_bpf hooks */
! 2841: snprintf(hook, sizeof(hook), "i%d", b->id);
! 2842:
! 2843: memset(&u, 0, sizeof(u));
! 2844: strcpy(hp->thisHook, "ppp");
! 2845: hp->bpf_prog_len = TCPSYN_PROG_LEN;
! 2846: memcpy(&hp->bpf_prog, &gTCPSYNProg,
! 2847: TCPSYN_PROG_LEN * sizeof(*gTCPSYNProg));
! 2848: strcpy(hp->ifMatch, MPD_HOOK_TCPMSS_IN);
! 2849: strcpy(hp->ifNotMatch, "iface");
! 2850:
! 2851: if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
! 2852: NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
! 2853: Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
! 2854:
! 2855: memset(&u, 0, sizeof(u));
! 2856: strcpy(hp->thisHook, MPD_HOOK_TCPMSS_IN);
! 2857: hp->bpf_prog_len = NOMATCH_PROG_LEN;
! 2858: memcpy(&hp->bpf_prog, &gNoMatchProg,
! 2859: NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
! 2860: strcpy(hp->ifMatch, "ppp");
! 2861: strcpy(hp->ifNotMatch, "ppp");
! 2862:
! 2863: if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
! 2864: NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
! 2865: Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
! 2866:
! 2867: snprintf(hook, sizeof(hook), "o%d", b->id);
! 2868: memset(&u, 0, sizeof(u));
! 2869: strcpy(hp->thisHook, "iface");
! 2870: hp->bpf_prog_len = TCPSYN_PROG_LEN;
! 2871: memcpy(&hp->bpf_prog, &gTCPSYNProg,
! 2872: TCPSYN_PROG_LEN * sizeof(*gTCPSYNProg));
! 2873: strcpy(hp->ifMatch, MPD_HOOK_TCPMSS_OUT);
! 2874: strcpy(hp->ifNotMatch, "ppp");
! 2875:
! 2876: if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
! 2877: NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
! 2878: Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
! 2879:
! 2880: memset(&u, 0, sizeof(u));
! 2881: strcpy(hp->thisHook, MPD_HOOK_TCPMSS_OUT);
! 2882: hp->bpf_prog_len = NOMATCH_PROG_LEN;
! 2883: memcpy(&hp->bpf_prog, &gNoMatchProg,
! 2884: NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
! 2885: strcpy(hp->ifMatch, "iface");
! 2886: strcpy(hp->ifNotMatch, "iface");
! 2887:
! 2888: if (NgSendMsg(gLinksCsock, hook, NGM_BPF_COOKIE,
! 2889: NGM_BPF_SET_PROGRAM, hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0)
! 2890: Perror("[%s] can't set %s node program", b->name, NG_BPF_NODE_TYPE);
! 2891:
! 2892: #endif /* USE_NG_TCPMSS */
! 2893: }
! 2894:
! 2895: static void
! 2896: IfaceShutdownMSS(Bund b)
! 2897: {
! 2898: char path[NG_PATHSIZ];
! 2899:
! 2900: #ifdef USE_NG_TCPMSS
! 2901: snprintf(path, sizeof(path), "mpd%d-%s-mss:", gPid, b->name);
! 2902: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 2903: #else
! 2904: snprintf(path, sizeof(path), "i%d", b->id);
! 2905: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 2906: #endif
! 2907: }
! 2908: #endif /* defined(USE_NG_TCPMSS) || (!defined(USE_NG_TCPMSS) && defined(USE_NG_BPF)) */
! 2909:
! 2910: #ifdef USE_NG_BPF
! 2911: static int
! 2912: IfaceInitLimits(Bund b, char *path, char *hook)
! 2913: {
! 2914: struct ngm_mkpeer mp;
! 2915: struct ngm_name nm;
! 2916:
! 2917: if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
! 2918:
! 2919: Log(LG_IFACE2, ("[%s] IFACE: Connecting limits", b->name));
! 2920:
! 2921: /* Create a bpf node for traffic filtering. */
! 2922: strcpy(mp.type, NG_BPF_NODE_TYPE);
! 2923: strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
! 2924: strcpy(mp.peerhook, "ppp");
! 2925: if (NgSendMsg(gLinksCsock, path,
! 2926: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 2927: Perror("can't create %s node at \"%s\"->\"%s\"",
! 2928: NG_BPF_NODE_TYPE, path, mp.ourhook);
! 2929: goto fail;
! 2930: }
! 2931:
! 2932: strlcat(path, ".", NG_PATHSIZ);
! 2933: strlcat(path, hook, NG_PATHSIZ);
! 2934: strcpy(hook, "iface");
! 2935:
! 2936: b->iface.limitID = NgGetNodeID(gLinksCsock, path);
! 2937: if (b->iface.limitID == 0)
! 2938: Perror("can't get limits %s node ID", NG_BPF_NODE_TYPE);
! 2939:
! 2940: /* Set the new node's name. */
! 2941: snprintf(nm.name, sizeof(nm.name), "mpd%d-%s-lim", gPid, b->name);
! 2942: if (NgSendMsg(gLinksCsock, path,
! 2943: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 2944: Perror("can't name limits %s node", NG_BPF_NODE_TYPE);
! 2945: goto fail;
! 2946: }
! 2947:
! 2948: }
! 2949:
! 2950: return (0);
! 2951: fail:
! 2952: return (-1);
! 2953: }
! 2954:
! 2955: /*
! 2956: * BundConfigLimits()
! 2957: *
! 2958: * Configure the bpf & car nodes.
! 2959: */
! 2960:
! 2961: static void
! 2962: IfaceSetupLimits(Bund b)
! 2963: {
! 2964: #define ACL_MAX_PROGLEN 65536
! 2965: union {
! 2966: u_char buf[NG_BPF_HOOKPROG_SIZE(ACL_MAX_PROGLEN)];
! 2967: struct ng_bpf_hookprog hprog;
! 2968: } *hpu;
! 2969: struct ng_bpf_hookprog *hp;
! 2970: struct ngm_connect cn;
! 2971: int i;
! 2972:
! 2973: hpu = Malloc(MB_IFACE, sizeof(*hpu));
! 2974: hp = &hpu->hprog;
! 2975:
! 2976: if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
! 2977: char path[NG_PATHSIZ];
! 2978: int num, dir;
! 2979:
! 2980: snprintf(path, sizeof(path), "mpd%d-%s-lim:", gPid, b->name);
! 2981:
! 2982: for (dir = 0; dir < 2; dir++) {
! 2983: char inhook[2][NG_HOOKSIZ];
! 2984: char inhookn[2][NG_HOOKSIZ];
! 2985: char outhook[NG_HOOKSIZ];
! 2986: struct acl *l;
! 2987:
! 2988: if (dir == 0) {
! 2989: strcpy(inhook[0], "ppp");
! 2990: strcpy(outhook, "iface");
! 2991: } else {
! 2992: strcpy(inhook[0], "iface");
! 2993: strcpy(outhook, "ppp");
! 2994: }
! 2995: strcpy(inhook[1], "");
! 2996: num = 0;
! 2997: for (l = b->params.acl_limits[dir]; l; l = l->next) {
! 2998: char str[ACL_LEN];
! 2999: #define ACL_MAX_PARAMS 7 /* one more then max number of arguments */
! 3000: int ac;
! 3001: char *av[ACL_MAX_PARAMS];
! 3002: int p;
! 3003: char stathook[NG_HOOKSIZ];
! 3004: struct svcs *ss = NULL;
! 3005: struct svcssrc *sss = NULL;
! 3006:
! 3007: Log(LG_IFACE2, ("[%s] IFACE: limit %s#%d%s%s: '%s'",
! 3008: b->name, (dir?"out":"in"), l->number,
! 3009: ((l->name[0])?"#":""), l->name, l->rule));
! 3010: strlcpy(str, l->rule, sizeof(str));
! 3011: ac = ParseLine(str, av, ACL_MAX_PARAMS, 0);
! 3012: if (ac < 1 || ac >= ACL_MAX_PARAMS) {
! 3013: Log(LG_ERR, ("[%s] IFACE: incorrect limit: '%s'",
! 3014: b->name, l->rule));
! 3015: continue;
! 3016: }
! 3017:
! 3018: stathook[0] = 0;
! 3019: memset(hpu, 0, sizeof(hpu));
! 3020: /* Prepare filter */
! 3021: if (strcasecmp(av[0], "all") == 0) {
! 3022: hp->bpf_prog_len = MATCH_PROG_LEN;
! 3023: memcpy(&hp->bpf_prog, &gMatchProg,
! 3024: MATCH_PROG_LEN * sizeof(*gMatchProg));
! 3025: } else if (strncasecmp(av[0], "flt", 3) == 0) {
! 3026: struct acl *f;
! 3027: int flt;
! 3028:
! 3029: flt = atoi(av[0] + 3);
! 3030: if (flt <= 0 || flt > ACL_FILTERS) {
! 3031: Log(LG_ERR, ("[%s] IFACE: incorrect filter number: '%s'",
! 3032: b->name, av[0]));
! 3033: } else if ((f = b->params.acl_filters[flt - 1]) == NULL &&
! 3034: (f = acl_filters[flt - 1]) == NULL) {
! 3035: Log(LG_ERR, ("[%s] IFACE: Undefined filter: '%s'",
! 3036: b->name, av[0]));
! 3037: } else {
! 3038: struct bpf_program pr;
! 3039: char *buf;
! 3040: int bufbraces;
! 3041:
! 3042: #define ACL_BUF_SIZE 256*1024
! 3043: buf = Malloc(MB_IFACE, ACL_BUF_SIZE);
! 3044: buf[0] = 0;
! 3045: bufbraces = 0;
! 3046: while (f) {
! 3047: char *b1, *b2, *sbuf;
! 3048: sbuf = Mstrdup(MB_IFACE, f->rule);
! 3049: b2 = sbuf;
! 3050: b1 = strsep(&b2, " ");
! 3051: if (b2 != NULL) {
! 3052: if (strcasecmp(b1, "match") == 0) {
! 3053: strlcat(buf, "( ", ACL_BUF_SIZE);
! 3054: strlcat(buf, b2, ACL_BUF_SIZE);
! 3055: strlcat(buf, " ) ", ACL_BUF_SIZE);
! 3056: if (f->next) {
! 3057: strlcat(buf, "|| ( ", ACL_BUF_SIZE);
! 3058: bufbraces++;
! 3059: }
! 3060: } else if (strcasecmp(b1, "nomatch") == 0) {
! 3061: strlcat(buf, "( not ( ", ACL_BUF_SIZE);
! 3062: strlcat(buf, b2, ACL_BUF_SIZE);
! 3063: strlcat(buf, " ) ) ", ACL_BUF_SIZE);
! 3064: if (f->next) {
! 3065: strlcat(buf, "&& ( ", ACL_BUF_SIZE);
! 3066: bufbraces++;
! 3067: }
! 3068: } else {
! 3069: Log(LG_ERR, ("[%s] IFACE: filter action '%s' is unknown",
! 3070: b->name, b1));
! 3071: }
! 3072: };
! 3073: Freee(sbuf);
! 3074: f = f->next;
! 3075: }
! 3076: for (i = 0; i < bufbraces; i++)
! 3077: strlcat(buf, ") ", ACL_BUF_SIZE);
! 3078: Log(LG_IFACE2, ("[%s] IFACE: flt%d: '%s'",
! 3079: b->name, flt, buf));
! 3080:
! 3081: if (pcap_compile_nopcap((u_int)-1, DLT_RAW, &pr, buf, 1, 0xffffff00)) {
! 3082: Log(LG_ERR, ("[%s] IFACE: filter '%s' compilation error",
! 3083: b->name, av[0]));
! 3084: /* Incorrect matches nothing. */
! 3085: hp->bpf_prog_len = NOMATCH_PROG_LEN;
! 3086: memcpy(&hp->bpf_prog, &gNoMatchProg,
! 3087: NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
! 3088: } else if (pr.bf_len > ACL_MAX_PROGLEN) {
! 3089: Log(LG_ERR, ("[%s] IFACE: filter '%s' is too long",
! 3090: b->name, av[0]));
! 3091: pcap_freecode(&pr);
! 3092: /* Incorrect matches nothing. */
! 3093: hp->bpf_prog_len = NOMATCH_PROG_LEN;
! 3094: memcpy(&hp->bpf_prog, &gNoMatchProg,
! 3095: NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
! 3096: } else {
! 3097: hp->bpf_prog_len = pr.bf_len;
! 3098: memcpy(&hp->bpf_prog, pr.bf_insns,
! 3099: pr.bf_len * sizeof(struct bpf_insn));
! 3100: pcap_freecode(&pr);
! 3101: }
! 3102: Freee(buf);
! 3103: }
! 3104: } else {
! 3105: Log(LG_ERR, ("[%s] IFACE: incorrect filter: '%s'",
! 3106: b->name, av[0]));
! 3107: /* Incorrect matches nothing. */
! 3108: hp->bpf_prog_len = NOMATCH_PROG_LEN;
! 3109: memcpy(&hp->bpf_prog, &gNoMatchProg,
! 3110: NOMATCH_PROG_LEN * sizeof(*gNoMatchProg));
! 3111: }
! 3112:
! 3113: /* Prepare action */
! 3114: p = 1;
! 3115: if (ac == 1) {
! 3116: if (!l->next) {
! 3117: strcpy(hp->ifMatch, outhook);
! 3118: strcpy(inhookn[0], "");
! 3119: } else {
! 3120: sprintf(hp->ifMatch, "%d-%d-m", dir, num);
! 3121: sprintf(inhookn[0], "%d-%d-mi", dir, num);
! 3122:
! 3123: /* Connect nomatch hook to bpf itself. */
! 3124: strcpy(cn.ourhook, hp->ifMatch);
! 3125: strcpy(cn.path, path);
! 3126: strcpy(cn.peerhook, inhookn[0]);
! 3127: if (NgSendMsg(gLinksCsock, path,
! 3128: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 3129: Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 3130: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 3131: }
! 3132: strcpy(stathook, inhookn[0]);
! 3133: }
! 3134: } else if (strcasecmp(av[p], "pass") == 0) {
! 3135: strcpy(hp->ifMatch, outhook);
! 3136: strcpy(inhookn[0], "");
! 3137: } else if (strcasecmp(av[p], "deny") == 0) {
! 3138: strcpy(hp->ifMatch, "deny");
! 3139: strcpy(inhookn[0], "");
! 3140: #ifdef USE_NG_CAR
! 3141: } else if ((strcasecmp(av[p], "shape") == 0) ||
! 3142: (strcasecmp(av[p], "rate-limit") == 0)) {
! 3143: struct ngm_mkpeer mp;
! 3144: struct ng_car_bulkconf car;
! 3145: char tmppath[NG_PATHSIZ];
! 3146:
! 3147: sprintf(hp->ifMatch, "%d-%d-m", dir, num);
! 3148:
! 3149: /* Create a car node for traffic shaping. */
! 3150: strcpy(mp.type, NG_CAR_NODE_TYPE);
! 3151: snprintf(mp.ourhook, sizeof(mp.ourhook), "%d-%d-m", dir, num);
! 3152: strcpy(mp.peerhook, ((dir == 0)?NG_CAR_HOOK_LOWER:NG_CAR_HOOK_UPPER));
! 3153: if (NgSendMsg(gLinksCsock, path,
! 3154: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 3155: Perror("[%s] IFACE: can't create %s node at \"%s\"->\"%s\"",
! 3156: b->name, NG_CAR_NODE_TYPE, path, mp.ourhook);
! 3157: }
! 3158:
! 3159: snprintf(tmppath, sizeof(tmppath), "%s%d-%d-m", path, dir, num);
! 3160:
! 3161: /* Connect car to bpf. */
! 3162: snprintf(cn.ourhook, sizeof(cn.ourhook), "%d-%d-mi", dir, num);
! 3163: strlcpy(cn.path, tmppath, sizeof(cn.path));
! 3164: strcpy(cn.peerhook, ((dir == 0)?NG_CAR_HOOK_UPPER:NG_CAR_HOOK_LOWER));
! 3165: if (NgSendMsg(gLinksCsock, path,
! 3166: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 3167: Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 3168: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 3169: }
! 3170:
! 3171: bzero(&car, sizeof(car));
! 3172:
! 3173: if (strcasecmp(av[p], "shape") == 0) {
! 3174: car.upstream.mode = NG_CAR_SHAPE;
! 3175: } else {
! 3176: car.upstream.mode = NG_CAR_RED;
! 3177: }
! 3178: p++;
! 3179:
! 3180: if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
! 3181: car.upstream.cir = atol(av[p]);
! 3182: p++;
! 3183: if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
! 3184: car.upstream.cbs = atol(av[p]);
! 3185: p++;
! 3186: if ((ac > p) && (av[p][0] >= '0') && (av[p][0] <= '9')) {
! 3187: car.upstream.ebs = atol(av[p]);
! 3188: p++;
! 3189: } else {
! 3190: car.upstream.ebs = car.upstream.cbs * 2;
! 3191: }
! 3192: } else {
! 3193: car.upstream.cbs = car.upstream.cir / 8;
! 3194: car.upstream.ebs = car.upstream.cbs * 2;
! 3195: }
! 3196: } else {
! 3197: car.upstream.cir = 8000;
! 3198: car.upstream.cbs = car.upstream.cir / 8;
! 3199: car.upstream.ebs = car.upstream.cbs * 2;
! 3200: }
! 3201: car.upstream.green_action = NG_CAR_ACTION_FORWARD;
! 3202: car.upstream.yellow_action = NG_CAR_ACTION_FORWARD;
! 3203: car.upstream.red_action = NG_CAR_ACTION_DROP;
! 3204:
! 3205: car.downstream = car.upstream;
! 3206:
! 3207: if (NgSendMsg(gLinksCsock, tmppath,
! 3208: NGM_CAR_COOKIE, NGM_CAR_SET_CONF, &car, sizeof(car)) < 0) {
! 3209: Perror("[%s] IFACE: can't set %s configuration",
! 3210: b->name, NG_CAR_NODE_TYPE);
! 3211: }
! 3212:
! 3213: if (ac > p) {
! 3214: if (strcasecmp(av[p], "pass") == 0) {
! 3215: union {
! 3216: u_char buf[NG_BPF_HOOKPROG_SIZE(MATCH_PROG_LEN)];
! 3217: struct ng_bpf_hookprog hprog;
! 3218: } hpu1;
! 3219: struct ng_bpf_hookprog *const hp1 = &hpu1.hprog;
! 3220:
! 3221: memset(&hpu1, 0, sizeof(hpu1));
! 3222: strcpy(hp1->ifMatch, outhook);
! 3223: strcpy(hp1->ifNotMatch, outhook);
! 3224: hp1->bpf_prog_len = MATCH_PROG_LEN;
! 3225: memcpy(&hp1->bpf_prog, &gMatchProg,
! 3226: MATCH_PROG_LEN * sizeof(*gMatchProg));
! 3227: sprintf(hp1->thisHook, "%d-%d-mi", dir, num);
! 3228: if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM,
! 3229: hp1, NG_BPF_HOOKPROG_SIZE(hp1->bpf_prog_len)) < 0) {
! 3230: Perror("[%s] IFACE: can't set %s node program",
! 3231: b->name, NG_BPF_NODE_TYPE);
! 3232: }
! 3233:
! 3234: strcpy(stathook, hp1->thisHook);
! 3235: strcpy(inhookn[0], "");
! 3236: } else {
! 3237: Log(LG_ERR, ("[%s] IFACE: unknown action: '%s'",
! 3238: b->name, av[p]));
! 3239: strcpy(inhookn[0], "");
! 3240: }
! 3241: } else {
! 3242: sprintf(inhookn[0], "%d-%d-mi", dir, num);
! 3243: strcpy(stathook, inhookn[0]);
! 3244: }
! 3245: #endif /* USE_NG_CAR */
! 3246: } else {
! 3247: Log(LG_ERR, ("[%s] IFACE: unknown action: '%s'",
! 3248: b->name, av[1]));
! 3249: strcpy(inhookn[0], "");
! 3250: }
! 3251:
! 3252: /* Prepare nomatch */
! 3253: if (l->next && strcasecmp(av[0], "all")) {
! 3254: /* If there is next limit and there is possible nomatch,
! 3255: * then pass nomatch there. */
! 3256: sprintf(hp->ifNotMatch, "%d-%d-n", dir, num);
! 3257: sprintf(inhookn[1], "%d-%d-ni", dir, num);
! 3258:
! 3259: /* Connect nomatch hook to bpf itself. */
! 3260: strcpy(cn.ourhook, hp->ifNotMatch);
! 3261: strcpy(cn.path, path);
! 3262: strcpy(cn.peerhook, inhookn[1]);
! 3263: if (NgSendMsg(gLinksCsock, path,
! 3264: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 3265: Perror("[%s] IFACE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 3266: b->name, path, cn.ourhook, cn.path, cn.peerhook);
! 3267: }
! 3268: } else {
! 3269: /* There is no next limit, pass nomatch. */
! 3270: strcpy(hp->ifNotMatch, outhook);
! 3271: strcpy(inhookn[1], "");
! 3272: }
! 3273:
! 3274: /* Remember how to collect stats for this limit */
! 3275: if (l->name[0]) {
! 3276: SLIST_FOREACH(ss, &b->iface.ss[dir], next) {
! 3277: if (strcmp(ss->name, l->name) == 0)
! 3278: break;
! 3279: }
! 3280: if (ss == NULL) {
! 3281: ss = Malloc(MB_IFACE, sizeof(*ss));
! 3282: strlcpy(ss->name, l->name, sizeof(ss->name));
! 3283: SLIST_INIT(&ss->src);
! 3284: SLIST_INSERT_HEAD(&b->iface.ss[dir], ss, next);
! 3285: }
! 3286: if (stathook[0]) {
! 3287: sss = Malloc(MB_IFACE, sizeof(*sss));
! 3288: strlcpy(sss->hook, stathook, sizeof(sss->hook));
! 3289: sss->type = SSSS_IN;
! 3290: SLIST_INSERT_HEAD(&ss->src, sss, next);
! 3291: }
! 3292: }
! 3293:
! 3294: for (i = 0; i < 2; i++) {
! 3295: if (inhook[i][0] != 0) {
! 3296: if (l->name[0] && !stathook[0]) {
! 3297: sss = Malloc(MB_IFACE, sizeof(*sss));
! 3298: strlcpy(sss->hook, inhook[i], sizeof(sss->hook));
! 3299: sss->type = SSSS_MATCH;
! 3300: SLIST_INSERT_HEAD(&ss->src, sss, next);
! 3301: }
! 3302:
! 3303: strcpy(hp->thisHook, inhook[i]);
! 3304: if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM,
! 3305: hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0) {
! 3306: Perror("[%s] IFACE: can't set %s node program",
! 3307: b->name, NG_BPF_NODE_TYPE);
! 3308: }
! 3309: }
! 3310: strcpy(inhook[i], inhookn[i]);
! 3311: }
! 3312:
! 3313: num++;
! 3314: }
! 3315:
! 3316: /* Connect left hooks to output */
! 3317: for (i = 0; i < 2; i++) {
! 3318: if (inhook[i][0] != 0) {
! 3319: memset(hpu, 0, sizeof(*hpu));
! 3320: strcpy(hp->thisHook, inhook[i]);
! 3321: hp->bpf_prog_len = MATCH_PROG_LEN;
! 3322: memcpy(&hp->bpf_prog, &gMatchProg,
! 3323: MATCH_PROG_LEN * sizeof(*gMatchProg));
! 3324: strcpy(hp->ifMatch, outhook);
! 3325: strcpy(hp->ifNotMatch, outhook);
! 3326: if (NgSendMsg(gLinksCsock, path, NGM_BPF_COOKIE, NGM_BPF_SET_PROGRAM,
! 3327: hp, NG_BPF_HOOKPROG_SIZE(hp->bpf_prog_len)) < 0) {
! 3328: Perror("[%s] IFACE: can't set %s node %s %s program (2)",
! 3329: b->name, NG_BPF_NODE_TYPE, path, hp->thisHook);
! 3330: }
! 3331: }
! 3332: }
! 3333: }
! 3334: }
! 3335: Freee(hpu);
! 3336: }
! 3337:
! 3338: static void
! 3339: IfaceShutdownLimits(Bund b)
! 3340: {
! 3341: char path[NG_PATHSIZ];
! 3342: struct svcs *ss;
! 3343: struct svcssrc *sss;
! 3344: struct svcstat curstats;
! 3345: int i;
! 3346:
! 3347: if (b->n_up > 0) {
! 3348: bzero(&curstats, sizeof(curstats));
! 3349: IfaceGetStats(b, &curstats);
! 3350: IfaceAddStats(&b->iface.prevstats, &curstats);
! 3351: IfaceFreeStats(&curstats);
! 3352: }
! 3353:
! 3354: if (b->params.acl_limits[0] || b->params.acl_limits[1]) {
! 3355: snprintf(path, sizeof(path), "[%x]:", b->iface.limitID);
! 3356: NgFuncShutdownNode(gLinksCsock, b->name, path);
! 3357: }
! 3358:
! 3359: for (i = 0; i < ACL_DIRS; i++) {
! 3360: while ((ss = SLIST_FIRST(&b->iface.ss[i])) != NULL) {
! 3361: while ((sss = SLIST_FIRST(&ss->src)) != NULL) {
! 3362: SLIST_REMOVE_HEAD(&ss->src, next);
! 3363: Freee(sss);
! 3364: }
! 3365: SLIST_REMOVE_HEAD(&b->iface.ss[i], next);
! 3366: Freee(ss);
! 3367: }
! 3368: }
! 3369: }
! 3370:
! 3371: void
! 3372: IfaceGetStats(Bund b, struct svcstat *stat)
! 3373: {
! 3374: char path[NG_PATHSIZ];
! 3375: struct svcs *ss;
! 3376: struct svcssrc *sss;
! 3377: int dir;
! 3378:
! 3379: union {
! 3380: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_bpf_hookstat)];
! 3381: struct ng_mesg reply;
! 3382: } u;
! 3383: struct ng_bpf_hookstat *const hs = (struct ng_bpf_hookstat *)(void *)u.reply.data;
! 3384:
! 3385: snprintf(path, sizeof(path), "[%x]:", b->iface.limitID);
! 3386: for (dir = 0; dir < ACL_DIRS; dir++) {
! 3387: SLIST_FOREACH(ss, &b->iface.ss[dir], next) {
! 3388: struct svcstatrec *ssr;
! 3389:
! 3390: SLIST_FOREACH(ssr, &stat->stat[dir], next) {
! 3391: if (strcmp(ssr->name, ss->name) == 0)
! 3392: break;
! 3393: }
! 3394: if (!ssr) {
! 3395: ssr = Malloc(MB_IFACE, sizeof(*ssr));
! 3396: strlcpy(ssr->name, ss->name, sizeof(ssr->name));
! 3397: SLIST_INSERT_HEAD(&stat->stat[dir], ssr, next);
! 3398: }
! 3399:
! 3400: SLIST_FOREACH(sss, &ss->src, next) {
! 3401: if (NgSendMsg(gLinksCsock, path,
! 3402: NGM_BPF_COOKIE, NGM_BPF_GET_STATS, sss->hook, strlen(sss->hook)+1) < 0)
! 3403: continue;
! 3404: if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0)
! 3405: continue;
! 3406:
! 3407: switch(sss->type) {
! 3408: case SSSS_IN:
! 3409: ssr->Packets += hs->recvFrames;
! 3410: ssr->Octets += hs->recvOctets;
! 3411: break;
! 3412: case SSSS_MATCH:
! 3413: ssr->Packets += hs->recvMatchFrames;
! 3414: ssr->Octets += hs->recvMatchOctets;
! 3415: break;
! 3416: case SSSS_NOMATCH:
! 3417: ssr->Packets += hs->recvFrames - hs->recvMatchFrames;
! 3418: ssr->Octets += hs->recvOctets - hs->recvMatchOctets;
! 3419: break;
! 3420: case SSSS_OUT:
! 3421: ssr->Packets += hs->xmitFrames;
! 3422: ssr->Octets += hs->xmitOctets;
! 3423: break;
! 3424: }
! 3425: }
! 3426: }
! 3427: }
! 3428: }
! 3429:
! 3430: void
! 3431: IfaceAddStats(struct svcstat *stat1, struct svcstat *stat2)
! 3432: {
! 3433: struct svcstatrec *ssr1, *ssr2;
! 3434: int dir;
! 3435:
! 3436: for (dir = 0; dir < ACL_DIRS; dir++) {
! 3437: SLIST_FOREACH(ssr2, &stat2->stat[dir], next) {
! 3438: SLIST_FOREACH(ssr1, &stat1->stat[dir], next)
! 3439: if (strcmp(ssr1->name, ssr2->name) == 0) {
! 3440: break;
! 3441: }
! 3442: if (!ssr1) {
! 3443: ssr1 = Malloc(MB_IFACE, sizeof(*ssr1));
! 3444: strlcpy(ssr1->name, ssr2->name, sizeof(ssr1->name));
! 3445: SLIST_INSERT_HEAD(&stat1->stat[dir], ssr1, next);
! 3446: }
! 3447: ssr1->Packets += ssr2->Packets;
! 3448: ssr1->Octets += ssr2->Octets;
! 3449: }
! 3450: }
! 3451: }
! 3452:
! 3453: void
! 3454: IfaceFreeStats(struct svcstat *stat)
! 3455: {
! 3456: struct svcstatrec *ssr;
! 3457: int i;
! 3458:
! 3459: for (i = 0; i < ACL_DIRS; i++) {
! 3460: while ((ssr = SLIST_FIRST(&stat->stat[i])) != NULL) {
! 3461: SLIST_REMOVE_HEAD(&stat->stat[i], next);
! 3462: Freee(ssr);
! 3463: }
! 3464: }
! 3465: }
! 3466: #endif /* USE_NG_BPF */
! 3467:
! 3468: /*
! 3469: * IfaceSetName()
! 3470: */
! 3471:
! 3472: int
! 3473: IfaceSetName(Bund b, const char * ifname)
! 3474: {
! 3475: IfaceState const iface = &b->iface;
! 3476: struct ifreq ifr;
! 3477: int s;
! 3478:
! 3479: /* Do not rename interface on template */
! 3480: if (b->tmpl)
! 3481: return(0);
! 3482:
! 3483: /* Do not wait ioctl error "file already exist" */
! 3484: if (strncmp(iface->ifname, ifname, sizeof(iface->ifname)) == 0)
! 3485: return(0);
! 3486:
! 3487: /* Get socket */
! 3488: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 3489: Log(LG_ERR, ("[%s] IFACE: Can't get socket to set name", b->name));
! 3490: return(-1);
! 3491: }
! 3492:
! 3493: /* Set name of interface */
! 3494: memset(&ifr, 0, sizeof(ifr));
! 3495: strlcpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
! 3496: ifr.ifr_data = (caddr_t)ifname;
! 3497: Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" name to \"%s\"",
! 3498: b->name, iface->ifname, ifname));
! 3499:
! 3500: if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
! 3501: Perror("[%s] IFACE: ioctl(%s, SIOCSIFNAME)", b->name, iface->ifname);
! 3502: close(s);
! 3503: return(-1);
! 3504: }
! 3505:
! 3506: close(s);
! 3507: /* Save name */
! 3508: strlcpy(iface->ifname, ifname, sizeof(iface->ifname));
! 3509: return(0);
! 3510: }
! 3511:
! 3512: #ifdef SIOCSIFDESCR
! 3513: /*
! 3514: * IfaceSetDescr()
! 3515: */
! 3516:
! 3517: int
! 3518: IfaceSetDescr(Bund b, const char * ifdescr)
! 3519: {
! 3520: IfaceState const iface = &b->iface;
! 3521: struct ifreq ifr;
! 3522: int s, ifdescr_maxlen;
! 3523: char *newdescr;
! 3524: size_t sz = sizeof(int);
! 3525:
! 3526: if (b->tmpl) {
! 3527: Log(LG_ERR, ("Impossible ioctl(SIOCSIFDESCR) on template"));
! 3528: return(-1);
! 3529: }
! 3530:
! 3531: if (sysctlbyname("net.ifdescr_maxlen", &ifdescr_maxlen, &sz, NULL, 0) < 0) {
! 3532: Perror("[%s] IFACE: sysctl net.ifdescr_maxlen failed", b->name);
! 3533: return(-1);
! 3534: }
! 3535:
! 3536: if (ifdescr_maxlen < strlen(ifdescr) + 1) {
! 3537: Log(LG_ERR, ("[%s] IFACE: Description too long, >%d characters",
! 3538: b->name, ifdescr_maxlen-1));
! 3539: return(-1);
! 3540: }
! 3541:
! 3542: /* Get socket */
! 3543: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 3544: Log(LG_ERR, ("[%s] IFACE: Can't get socket to set description", b->name));
! 3545: return(-1);
! 3546: }
! 3547:
! 3548: /* Set description of interface */
! 3549: memset(&ifr, 0, sizeof(ifr));
! 3550: strlcpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name));
! 3551: ifr.ifr_buffer.length = strlen(ifdescr) + 1;
! 3552: if (ifr.ifr_buffer.length == 1) {
! 3553: ifr.ifr_buffer.buffer = newdescr = NULL;
! 3554: ifr.ifr_buffer.length = 0;
! 3555: Log(LG_IFACE2, ("[%s] IFACE: clearing \"%s\" description",
! 3556: b->name, iface->ifname));
! 3557: } else {
! 3558: newdescr = Mstrdup(MB_IFACE, ifdescr);
! 3559: ifr.ifr_buffer.buffer = newdescr;
! 3560: Log(LG_IFACE2, ("[%s] IFACE: setting \"%s\" description to \"%s\"",
! 3561: b->name, iface->ifname, ifdescr));
! 3562: }
! 3563:
! 3564: if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0) {
! 3565: Perror("[%s] IFACE: ioctl(%s, SIOCSIFDESCR)", b->name, iface->ifname);
! 3566: Freee(newdescr);
! 3567: close(s);
! 3568: return(-1);
! 3569: }
! 3570: Freee(newdescr);
! 3571: close(s);
! 3572: return(0);
! 3573: }
! 3574: #endif /* SIOCSIFDESCR */
! 3575: #ifdef SIOCAIFGROUP
! 3576: /*
! 3577: * IfaceAddGroup()
! 3578: */
! 3579:
! 3580: int
! 3581: IfaceAddGroup(Bund b, const char * ifgroup)
! 3582: {
! 3583: IfaceState const iface = &b->iface;
! 3584: struct ifgroupreq ifgr;
! 3585: int s, i;
! 3586:
! 3587: /* Do not add group on template */
! 3588: if (b->tmpl)
! 3589: return(0);
! 3590:
! 3591: if (ifgroup[0] && isdigit(ifgroup[strlen(ifgroup) - 1])) {
! 3592: Perror("[%s] IFACE: groupnames may not end in a digit", b->name);
! 3593: return(-1);
! 3594: }
! 3595:
! 3596: /* Get socket */
! 3597: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 3598: Perror("[%s] IFACE: Can't get socket to add group", b->name);
! 3599: return(-1);
! 3600: }
! 3601:
! 3602: /* Add interface group */
! 3603: memset(&ifgr, 0, sizeof(ifgr));
! 3604: strlcpy(ifgr.ifgr_name, iface->ifname, sizeof(ifgr.ifgr_name));
! 3605: strlcpy(ifgr.ifgr_group, ifgroup, sizeof(ifgr.ifgr_group));
! 3606:
! 3607: Log(LG_IFACE2, ("[%s] IFACE: adding interface %s to group %s",
! 3608: b->name, iface->ifname, ifgroup));
! 3609:
! 3610: i = ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr);
! 3611: if (i < 0 && i != EEXIST) {
! 3612: Perror("[%s] IFACE: ioctl(%s, SIOCAIFGROUP)", b->name, iface->ifname);
! 3613: close(s);
! 3614: return(-1);
! 3615: }
! 3616:
! 3617: close(s);
! 3618: return(0);
! 3619: }
! 3620:
! 3621: /*
! 3622: * IfaceDelGroup()
! 3623: */
! 3624: int
! 3625: IfaceDelGroup(Bund b, const char * ifgroup)
! 3626: {
! 3627: IfaceState const iface = &b->iface;
! 3628: struct ifgroupreq ifgr;
! 3629: int s;
! 3630:
! 3631: /* Get socket */
! 3632: if ((s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
! 3633: Perror("[%s] IFACE: Can't get socket to delete from group", b->name);
! 3634: return(-1);
! 3635: }
! 3636:
! 3637: if (ifgroup[0] && isdigit(ifgroup[strlen(ifgroup) - 1])) {
! 3638: Perror("[%s] IFACE: groupnames may not end in a digit", b->name);
! 3639: return(-1);
! 3640: }
! 3641:
! 3642: /* Set interface group */
! 3643: memset(&ifgr, 0, sizeof(ifgr));
! 3644: strlcpy(ifgr.ifgr_name, iface->ifname, sizeof(ifgr.ifgr_name));
! 3645: strlcpy(ifgr.ifgr_group, ifgroup, sizeof(ifgr.ifgr_group));
! 3646:
! 3647: Log(LG_IFACE2, ("[%s] IFACE: remove interface %s from group %s",
! 3648: b->name, iface->ifname, ifgroup));
! 3649:
! 3650: if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1) {
! 3651: Perror("[%s] IFACE: ioctl(%s, SIOCDIFGROUP)", b->name, iface->ifname);
! 3652: close(s);
! 3653: return(-1);
! 3654: }
! 3655: close(s);
! 3656: return(0);
! 3657: }
! 3658: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>