Annotation of embedaddon/mpd/src/ngfunc.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * ngfunc.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 contributed by Sergey Korolew <dsATbittu.org.ru>
! 10: *
! 11: * Routines for doing netgraph stuff
! 12: *
! 13: */
! 14:
! 15: #include "defs.h"
! 16: #include "ppp.h"
! 17: #include "bund.h"
! 18: #include "ngfunc.h"
! 19: #include "input.h"
! 20: #include "ccp.h"
! 21: #include "netgraph.h"
! 22: #include "command.h"
! 23: #include "util.h"
! 24:
! 25: #ifdef USE_NG_BPF
! 26: #include <net/bpf.h>
! 27: #endif
! 28: #include <arpa/inet.h>
! 29:
! 30: #include <netgraph/ng_message.h>
! 31:
! 32: #include <netgraph/ng_socket.h>
! 33: #include <netgraph/ng_ksocket.h>
! 34: #include <netgraph/ng_iface.h>
! 35: #ifdef USE_NG_VJC
! 36: #include <netgraph/ng_vjc.h>
! 37: #endif
! 38: #ifdef USE_NG_BPF
! 39: #include <netgraph/ng_bpf.h>
! 40: #endif
! 41: #include <netgraph/ng_tee.h>
! 42: #ifdef USE_NG_TCPMSS
! 43: #include <netgraph/ng_tcpmss.h>
! 44: #endif
! 45: #ifdef USE_NG_NETFLOW
! 46: #include <netgraph/netflow/ng_netflow.h>
! 47: #if NGM_NETFLOW_COOKIE >= 1309868867
! 48: #include <netgraph/netflow/netflow.h>
! 49: #include <netgraph/netflow/netflow_v9.h>
! 50: #endif
! 51: #endif
! 52: #ifdef USE_NG_PRED1
! 53: #include <netgraph/ng_pred1.h>
! 54: #endif
! 55:
! 56: #include <netinet/ip_icmp.h>
! 57: #include <netinet/tcp.h>
! 58:
! 59: /*
! 60: * DEFINITIONS
! 61: */
! 62:
! 63: #define TEMPHOOK "temphook"
! 64: #define MAX_IFACE_CREATE 128
! 65:
! 66: /* Set menu options */
! 67: enum {
! 68: SET_PEER,
! 69: SET_SELF,
! 70: SET_TIMEOUTS,
! 71: #if NGM_NETFLOW_COOKIE >= 1309868867
! 72: SET_TEMPLATE,
! 73: SET_MTU,
! 74: SET_VERSION,
! 75: #endif
! 76: SET_NODE,
! 77: SET_HOOK
! 78: };
! 79:
! 80: /*
! 81: * INTERNAL FUNCTIONS
! 82: */
! 83:
! 84: #ifdef USE_NG_NETFLOW
! 85: static int NetflowSetCommand(Context ctx, int ac, char *av[], void *arg);
! 86: #endif
! 87:
! 88: /*
! 89: * GLOBAL VARIABLES
! 90: */
! 91:
! 92: #ifdef USE_NG_NETFLOW
! 93: const struct cmdtab NetflowSetCmds[] = {
! 94: { "peer {ip} {port}", "Set export destination" ,
! 95: NetflowSetCommand, NULL, 2, (void *) SET_PEER },
! 96: { "self {ip} [{port}]", "Set export source" ,
! 97: NetflowSetCommand, NULL, 2, (void *) SET_SELF },
! 98: { "timeouts {inactive} {active}", "Set NetFlow timeouts" ,
! 99: NetflowSetCommand, NULL, 2, (void *) SET_TIMEOUTS },
! 100: #if NGM_NETFLOW_COOKIE >= 1309868867
! 101: { "template {time} {packets}", "Set NetFlow v9 template" ,
! 102: NetflowSetCommand, NULL, 2, (void *) SET_TEMPLATE },
! 103: { "mtu {mtu}", "Set NetFlow v9 MTU" ,
! 104: NetflowSetCommand, NULL, 2, (void *) SET_MTU },
! 105: { "version {version}", "Set version to export" ,
! 106: NetflowSetCommand, NULL, 2, (void *) SET_VERSION },
! 107: #endif
! 108: { "node {name}", "Set node name to use" ,
! 109: NetflowSetCommand, NULL, 2, (void *) SET_NODE },
! 110: { "hook {number}", "Set initial hook number" ,
! 111: NetflowSetCommand, NULL, 2, (void *) SET_HOOK },
! 112: { NULL },
! 113: };
! 114: #endif
! 115:
! 116: /*
! 117: * INTERNAL VARIABLES
! 118: */
! 119:
! 120: #ifdef USE_NG_TCPMSS
! 121: u_char gTcpMSSNode = FALSE;
! 122: #endif
! 123: #ifdef USE_NG_NETFLOW
! 124: u_char gNetflowNode = FALSE;
! 125: u_char gNetflowNodeShutdown = TRUE;
! 126: char gNetflowNodeName[64] = "mpd-nf";
! 127: ng_ID_t gNetflowNodeID = 0;
! 128: u_int gNetflowIface = 0;
! 129: struct sockaddr_storage gNetflowExport;
! 130: struct sockaddr_storage gNetflowSource;
! 131: uint32_t gNetflowInactive = 0;
! 132: uint32_t gNetflowActive = 0;
! 133: #if NGM_NETFLOW_COOKIE >= 1309868867
! 134: uint16_t gNetflowTime = 0;
! 135: uint16_t gNetflowPackets = 0;
! 136: uint16_t gNetflowMTU = 0;
! 137: u_int gNetflowVer = 5;
! 138: #endif
! 139: #endif
! 140:
! 141: static int gNgStatSock=0;
! 142:
! 143:
! 144: #ifdef USE_NG_NETFLOW
! 145: int
! 146: NgFuncInitGlobalNetflow(void)
! 147: {
! 148: char path[NG_PATHSIZ];
! 149: struct ngm_mkpeer mp;
! 150: struct ngm_rmhook rm;
! 151: struct ngm_name nm;
! 152: int csock;
! 153:
! 154: /* Create a netgraph socket node */
! 155: if (NgMkSockNode(NULL, &csock, NULL) < 0) {
! 156: Perror("NETFLOW: Can't create %s node", NG_SOCKET_NODE_TYPE);
! 157: return (-1);
! 158: }
! 159:
! 160: /* If node exist just get it's ID. */
! 161: if (gNetflowNode) {
! 162: snprintf(path, sizeof(path), "%s:", gNetflowNodeName);
! 163: gNetflowNodeID = NgGetNodeID(csock, path);
! 164: close(csock);
! 165: return (0);
! 166: }
! 167:
! 168: snprintf(gNetflowNodeName, sizeof(gNetflowNodeName), "mpd%d-nf", gPid);
! 169:
! 170: /* Create a global netflow node. */
! 171: strcpy(mp.type, NG_NETFLOW_NODE_TYPE);
! 172: strcpy(mp.ourhook, TEMPHOOK);
! 173: strcpy(mp.peerhook, NG_NETFLOW_HOOK_DATA "0");
! 174: if (NgSendMsg(csock, ".:",
! 175: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 176: Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
! 177: mp.type, ".:", mp.ourhook);
! 178: goto fail;
! 179: }
! 180:
! 181: /* Get new node ID. */
! 182: gNetflowNodeID = NgGetNodeID(csock, TEMPHOOK);
! 183:
! 184: /* Set the new node's name. */
! 185: strcpy(nm.name, gNetflowNodeName);
! 186: if (NgSendMsg(csock, TEMPHOOK,
! 187: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 188: Perror("NETFLOW: Can't name %s node", NG_NETFLOW_NODE_TYPE);
! 189: goto fail;
! 190: }
! 191:
! 192: /* Connect ng_ksocket(4) node for export. */
! 193: strcpy(mp.type, NG_KSOCKET_NODE_TYPE);
! 194: #if NGM_NETFLOW_COOKIE >= 1309868867
! 195: if (gNetflowVer == 5) {
! 196: #endif
! 197: strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT);
! 198: #if NGM_NETFLOW_COOKIE >= 1309868867
! 199: } else {
! 200: strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT9);
! 201: }
! 202: #endif
! 203: if (gNetflowExport.ss_family==AF_INET6) {
! 204: snprintf(mp.peerhook, sizeof(mp.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
! 205: } else {
! 206: snprintf(mp.peerhook, sizeof(mp.peerhook), "inet/dgram/udp");
! 207: }
! 208: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
! 209: if (NgSendMsg(csock, path,
! 210: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 211: Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
! 212: mp.type, path, mp.ourhook);
! 213: goto fail;
! 214: }
! 215:
! 216: /* Configure timeouts for ng_netflow(4). */
! 217: if (gNetflowInactive != 0 && gNetflowActive != 0) {
! 218: struct ng_netflow_settimeouts nf_settime;
! 219:
! 220: nf_settime.inactive_timeout = gNetflowInactive;
! 221: nf_settime.active_timeout = gNetflowActive;
! 222:
! 223: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
! 224: NGM_NETFLOW_SETTIMEOUTS, &nf_settime, sizeof(nf_settime)) < 0) {
! 225: Perror("NETFLOW: Can't set timeouts on netflow %s node",
! 226: NG_NETFLOW_NODE_TYPE);
! 227: goto fail2;
! 228: }
! 229: }
! 230:
! 231: #if NGM_NETFLOW_COOKIE >= 1309868867
! 232: if (gNetflowTime != 0 && gNetflowPackets != 0) {
! 233: struct ng_netflow_settemplate nf_settempl;
! 234:
! 235: nf_settempl.time = gNetflowTime;
! 236: nf_settempl.packets = gNetflowPackets;
! 237: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
! 238: NGM_NETFLOW_SETTEMPLATE, &nf_settempl, sizeof(nf_settempl)) < 0) {
! 239: Perror("NETFLOW: Can't set NetFlow v9 template on netflow %s node",
! 240: NG_NETFLOW_NODE_TYPE);
! 241: goto fail2;
! 242: }
! 243: }
! 244:
! 245: if (gNetflowMTU != 0) {
! 246: struct ng_netflow_setmtu nf_setmtu;
! 247:
! 248: nf_setmtu.mtu = gNetflowMTU;
! 249: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
! 250: NGM_NETFLOW_SETMTU, &nf_setmtu, sizeof(nf_setmtu)) < 0) {
! 251: Perror("NETFLOW: Can't set NetFlow v9 MTU on netflow %s node",
! 252: NG_NETFLOW_NODE_TYPE);
! 253: goto fail2;
! 254: }
! 255: }
! 256: #endif
! 257:
! 258: /* Configure export destination and source on ng_ksocket(4). */
! 259: #if NGM_NETFLOW_COOKIE >= 1309868867
! 260: if (gNetflowVer == 5) {
! 261: #endif
! 262: strlcat(path, NG_NETFLOW_HOOK_EXPORT, sizeof(path));
! 263: #if NGM_NETFLOW_COOKIE >= 1309868867
! 264: } else {
! 265: strlcat(path, NG_NETFLOW_HOOK_EXPORT9, sizeof(path));
! 266: }
! 267: #endif
! 268: if (gNetflowSource.ss_len != 0) {
! 269: if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
! 270: NGM_KSOCKET_BIND, &gNetflowSource, sizeof(gNetflowSource)) < 0) {
! 271: Perror("NETFLOW: Can't bind export %s node", NG_KSOCKET_NODE_TYPE);
! 272: goto fail2;
! 273: }
! 274: }
! 275: if (gNetflowExport.ss_len != 0) {
! 276: if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
! 277: NGM_KSOCKET_CONNECT, &gNetflowExport, sizeof(gNetflowExport)) < 0) {
! 278: Perror("NETFLOW: Can't connect export %s node", NG_KSOCKET_NODE_TYPE);
! 279: goto fail2;
! 280: }
! 281: }
! 282:
! 283: /* Set the new node's name. */
! 284: snprintf(nm.name, sizeof(nm.name), "mpd%d-nfso", gPid);
! 285: if (NgSendMsg(csock, path,
! 286: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
! 287: Perror("NETFLOW: Can't name %s node", NG_KSOCKET_NODE_TYPE);
! 288: goto fail2;
! 289: }
! 290:
! 291: /* Disconnect temporary hook. */
! 292: memset(&rm, 0, sizeof(rm));
! 293: strncpy(rm.ourhook, TEMPHOOK, sizeof(rm.ourhook));
! 294: if (NgSendMsg(csock, ".:",
! 295: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
! 296: Perror("can't remove hook %s", TEMPHOOK);
! 297: goto fail2;
! 298: }
! 299: gNetflowNode = TRUE;
! 300: close(csock);
! 301:
! 302: return (0);
! 303: fail2:
! 304: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
! 305: NgFuncShutdownNode(csock, "netflow", path);
! 306: fail:
! 307: gNetflowNodeID = 0;
! 308: close(csock);
! 309: return (-1);
! 310: }
! 311: #endif
! 312:
! 313: /*
! 314: * NgFuncCreateIface()
! 315: *
! 316: * Create a new netgraph interface.
! 317: */
! 318:
! 319: int
! 320: NgFuncCreateIface(Bund b, char *buf, int max)
! 321: {
! 322: union {
! 323: u_char buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
! 324: struct ng_mesg reply;
! 325: } u;
! 326: struct nodeinfo *const ni = (struct nodeinfo *)(void *)u.reply.data;
! 327: struct ngm_rmhook rm;
! 328: struct ngm_mkpeer mp;
! 329: int rtn = 0;
! 330:
! 331: /* Create iface node (as a temporary peer of the socket node) */
! 332: strcpy(mp.type, NG_IFACE_NODE_TYPE);
! 333: strcpy(mp.ourhook, TEMPHOOK);
! 334: strcpy(mp.peerhook, NG_IFACE_HOOK_INET);
! 335: if (NgSendMsg(gLinksCsock, ".:",
! 336: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
! 337: Log(LG_ERR, ("[%s] can't create %s node at \"%s\"->\"%s\": %s %d",
! 338: b->name, NG_IFACE_NODE_TYPE, ".:", mp.ourhook, strerror(errno), gLinksCsock));
! 339: return(-1);
! 340: }
! 341:
! 342: /* Get the new node's name */
! 343: if (NgSendMsg(gLinksCsock, TEMPHOOK,
! 344: NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
! 345: Perror("[%s] %s", b->name, "NGM_NODEINFO");
! 346: rtn = -1;
! 347: goto done;
! 348: }
! 349: if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) {
! 350: Perror("[%s] reply from %s", b->name, NG_IFACE_NODE_TYPE);
! 351: rtn = -1;
! 352: goto done;
! 353: }
! 354: strlcpy(buf, ni->name, max);
! 355:
! 356: done:
! 357: /* Disconnect temporary hook */
! 358: strcpy(rm.ourhook, TEMPHOOK);
! 359: if (NgSendMsg(gLinksCsock, ".:",
! 360: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
! 361: Perror("[%s] can't remove hook %s", b->name, TEMPHOOK);
! 362: rtn = -1;
! 363: }
! 364:
! 365: /* Done */
! 366: return(rtn);
! 367: }
! 368:
! 369: /*
! 370: * NgFuncShutdownGlobal()
! 371: *
! 372: * Shutdown nodes, that are shared between bundles.
! 373: */
! 374:
! 375: void
! 376: NgFuncShutdownGlobal(void)
! 377: {
! 378: #ifdef USE_NG_NETFLOW
! 379: char path[NG_PATHSIZ];
! 380: int csock;
! 381:
! 382: if (gNetflowNode == FALSE || gNetflowNodeShutdown==FALSE)
! 383: return;
! 384:
! 385: /* Create a netgraph socket node */
! 386: if (NgMkSockNode(NULL, &csock, NULL) < 0) {
! 387: Perror("NgFuncShutdownGlobal: can't create %s node", NG_SOCKET_NODE_TYPE);
! 388: return;
! 389: }
! 390:
! 391: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
! 392: NgFuncShutdownNode(csock, "netflow", path);
! 393:
! 394: close(csock);
! 395: #endif
! 396: }
! 397:
! 398: /*
! 399: * NgFuncShutdownNode()
! 400: */
! 401:
! 402: int
! 403: NgFuncShutdownNode(int csock, const char *label, const char *path)
! 404: {
! 405: int rtn, retry = 10, delay = 1000;
! 406:
! 407: retry:
! 408: if ((rtn = NgSendMsg(csock, path,
! 409: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0)) < 0) {
! 410: if (errno == ENOBUFS && retry > 0) {
! 411: Log(LG_ERR, ("[%s] shutdown \"%s\": %s, retrying...",
! 412: label, path, strerror(errno)));
! 413: usleep(delay);
! 414: retry--;
! 415: delay *= 2;
! 416: goto retry;
! 417: }
! 418: if (errno != ENOENT) {
! 419: Perror("[%s] can't shutdown \"%s\"", label, path);
! 420: }
! 421: }
! 422: return(rtn);
! 423: }
! 424:
! 425: /*
! 426: * NgFuncSetConfig()
! 427: */
! 428:
! 429: void
! 430: NgFuncSetConfig(Bund b)
! 431: {
! 432: char path[NG_PATHSIZ];
! 433: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 434: if (NgSendMsg(gLinksCsock, path, NGM_PPP_COOKIE,
! 435: NGM_PPP_SET_CONFIG, &b->pppConfig, sizeof(b->pppConfig)) < 0) {
! 436: Perror("[%s] can't config %s", b->name, path);
! 437: DoExit(EX_ERRDEAD);
! 438: }
! 439: }
! 440:
! 441: /*
! 442: * NgFuncSendQuery()
! 443: */
! 444:
! 445: int
! 446: NgFuncSendQuery(const char *path, int cookie, int cmd, const void *args,
! 447: size_t arglen, struct ng_mesg *rbuf, size_t replen, char *raddr)
! 448: {
! 449:
! 450: if (!gNgStatSock) {
! 451: char name[NG_NODESIZ];
! 452:
! 453: /* Create a netgraph socket node */
! 454: snprintf(name, sizeof(name), "mpd%d-stats", gPid);
! 455: if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
! 456: Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
! 457: return(-1);
! 458: }
! 459: (void) fcntl(gNgStatSock, F_SETFD, 1);
! 460: }
! 461:
! 462: /* Send message */
! 463: if (NgSendMsg(gNgStatSock, path, cookie, cmd, args, arglen) < 0)
! 464: return (-1);
! 465:
! 466: /* Read message */
! 467: if (NgRecvMsg(gNgStatSock, rbuf, replen, raddr) < 0) {
! 468: Perror("NgFuncSendQuery: can't read unexpected message");
! 469: return (-1);
! 470: }
! 471:
! 472: return (0);
! 473: }
! 474:
! 475: /*
! 476: * NgFuncConnect()
! 477: */
! 478:
! 479: int
! 480: NgFuncConnect(int csock, char *label, const char *path, const char *hook,
! 481: const char *path2, const char *hook2)
! 482: {
! 483: struct ngm_connect cn;
! 484:
! 485: strlcpy(cn.path, path2, sizeof(cn.path));
! 486: strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
! 487: strlcpy(cn.peerhook, hook2, sizeof(cn.peerhook));
! 488: if (NgSendMsg(csock, path,
! 489: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
! 490: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
! 491: label, path, hook, path2, hook2);
! 492: return(-1);
! 493: }
! 494: return(0);
! 495: }
! 496:
! 497: /*
! 498: * NgFuncDisconnect()
! 499: */
! 500:
! 501: int
! 502: NgFuncDisconnect(int csock, char *label, const char *path, const char *hook)
! 503: {
! 504: struct ngm_rmhook rm;
! 505: int retry = 10, delay = 1000;
! 506:
! 507: /* Disconnect hook */
! 508: memset(&rm, 0, sizeof(rm));
! 509: strlcpy(rm.ourhook, hook, sizeof(rm.ourhook));
! 510: retry:
! 511: if (NgSendMsg(csock, path,
! 512: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
! 513: if (errno == ENOBUFS && retry > 0) {
! 514: Log(LG_ERR, ("[%s] remove hook %s from node \"%s\": %s, retrying...",
! 515: label, hook, path, strerror(errno)));
! 516: usleep(delay);
! 517: retry--;
! 518: delay *= 2;
! 519: goto retry;
! 520: }
! 521: Perror("[%s] can't remove hook %s from node \"%s\"", label, hook, path);
! 522: return(-1);
! 523: }
! 524: return(0);
! 525: }
! 526:
! 527: /*
! 528: * NgFuncWritePppFrame()
! 529: *
! 530: * Consumes the mbuf.
! 531: */
! 532:
! 533: int
! 534: NgFuncWritePppFrame(Bund b, int linkNum, int proto, Mbuf bp)
! 535: {
! 536: u_int16_t temp;
! 537:
! 538: /* Prepend ppp node bypass header */
! 539: temp = htons(linkNum);
! 540: bp = mbcopyback(bp, -4, &temp, 2);
! 541: temp = htons(proto);
! 542: bp = mbcopyback(bp, 2, &temp, 2);
! 543:
! 544: /* Debugging */
! 545: LogDumpBp(LG_FRAME, bp,
! 546: "[%s] xmit bypass frame link=%d proto=0x%04x",
! 547: b->name, (int16_t)linkNum, proto);
! 548:
! 549: if ((linkNum == NG_PPP_BUNDLE_LINKNUM && b->n_up == 0) ||
! 550: (linkNum != NG_PPP_BUNDLE_LINKNUM &&
! 551: (b->links[linkNum] == NULL ||
! 552: b->links[linkNum]->state != PHYS_STATE_UP))) {
! 553: Log(LG_FRAME, ("[%s] Bundle: No links ready to send packet", b->name));
! 554: mbfree(bp);
! 555: return (-1);
! 556: }
! 557:
! 558: /* Write frame */
! 559: return NgFuncWriteFrame(gLinksDsock, b->hook, b->name, bp);
! 560: }
! 561:
! 562: /*
! 563: * NgFuncWritePppFrameLink()
! 564: *
! 565: * Consumes the mbuf.
! 566: */
! 567:
! 568: int
! 569: NgFuncWritePppFrameLink(Link l, int proto, Mbuf bp)
! 570: {
! 571: u_int16_t temp;
! 572:
! 573: if (l->joined_bund) {
! 574: return (NgFuncWritePppFrame(l->bund, l->bundleIndex, proto, bp));
! 575: }
! 576:
! 577: /* Prepend framing */
! 578: temp = htons(0xff03);
! 579: bp = mbcopyback(bp, -4, &temp, 2);
! 580: temp = htons(proto);
! 581: bp = mbcopyback(bp, 2, &temp, 2);
! 582:
! 583: /* Debugging */
! 584: LogDumpBp(LG_FRAME, bp,
! 585: "[%s] xmit frame to link proto=0x%04x",
! 586: l->name, proto);
! 587:
! 588: if (l->state != PHYS_STATE_UP) {
! 589: Log(LG_FRAME, ("[%s] Link: Not ready to send packet", l->name));
! 590: mbfree(bp);
! 591: return (-1);
! 592: }
! 593:
! 594: /* Write frame */
! 595: return NgFuncWriteFrame(gLinksDsock, l->hook, l->name, bp);
! 596: }
! 597:
! 598: /*
! 599: * NgFuncWriteFrame()
! 600: *
! 601: * Consumes the mbuf.
! 602: */
! 603:
! 604: int
! 605: NgFuncWriteFrame(int dsock, const char *hookname, const char *label, Mbuf bp)
! 606: {
! 607: union {
! 608: u_char buf[sizeof(struct sockaddr_ng) + NG_HOOKSIZ];
! 609: struct sockaddr_ng sa_ng;
! 610: } u;
! 611: struct sockaddr_ng *ng = &u.sa_ng;
! 612: int rtn;
! 613:
! 614: /* Write frame */
! 615: if (bp == NULL)
! 616: return (-1);
! 617:
! 618: /* Set dest address */
! 619: memset(&u.buf, 0, sizeof(u.buf));
! 620: strlcpy(ng->sg_data, hookname, NG_HOOKSIZ);
! 621: ng->sg_family = AF_NETGRAPH;
! 622: ng->sg_len = 3 + strlen(ng->sg_data);
! 623:
! 624: rtn = sendto(dsock, MBDATAU(bp), MBLEN(bp),
! 625: 0, (struct sockaddr *)ng, ng->sg_len);
! 626:
! 627: /* ENOBUFS can be expected on some links, e.g., ng_pptpgre(4) */
! 628: if (rtn < 0 && errno != ENOBUFS) {
! 629: Perror("[%s] error writing len %d frame to %s",
! 630: label, MBLEN(bp), hookname);
! 631: }
! 632: mbfree(bp);
! 633: return (rtn);
! 634: }
! 635:
! 636: /*
! 637: * NgFuncClrStats()
! 638: *
! 639: * Clear link or whole bundle statistics
! 640: */
! 641:
! 642: int
! 643: NgFuncClrStats(Bund b, u_int16_t linkNum)
! 644: {
! 645: char path[NG_PATHSIZ];
! 646:
! 647: /* Get stats */
! 648: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 649: if (NgSendMsg(gLinksCsock, path,
! 650: NGM_PPP_COOKIE, NGM_PPP_CLR_LINK_STATS, &linkNum, sizeof(linkNum)) < 0) {
! 651: Perror("[%s] can't clear stats, link=%d", b->name, linkNum);
! 652: return (-1);
! 653: }
! 654: return(0);
! 655: }
! 656:
! 657: /*
! 658: * NgFuncGetStats()
! 659: *
! 660: * Get link or whole bundle statistics
! 661: */
! 662:
! 663: int
! 664: NgFuncGetStats(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat *statp)
! 665: {
! 666: union {
! 667: u_char buf[sizeof(struct ng_mesg)
! 668: + sizeof(struct ng_ppp_link_stat)];
! 669: struct ng_mesg reply;
! 670: } u;
! 671: char path[NG_PATHSIZ];
! 672:
! 673: /* Get stats */
! 674: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 675: if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS,
! 676: &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
! 677: Perror("[%s] can't get stats, link=%d", b->name, linkNum);
! 678: return -1;
! 679: }
! 680: if (statp != NULL)
! 681: memcpy(statp, u.reply.data, sizeof(*statp));
! 682: return(0);
! 683: }
! 684:
! 685: #ifdef NG_PPP_STATS64
! 686: /*
! 687: * NgFuncGetStats64()
! 688: *
! 689: * Get 64bit link or whole bundle statistics
! 690: */
! 691:
! 692: int
! 693: NgFuncGetStats64(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat64 *statp)
! 694: {
! 695: union {
! 696: u_char buf[sizeof(struct ng_mesg)
! 697: + sizeof(struct ng_ppp_link_stat64)];
! 698: struct ng_mesg reply;
! 699: } u;
! 700: char path[NG_PATHSIZ];
! 701:
! 702: /* Get stats */
! 703: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
! 704: if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS64,
! 705: &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
! 706: Perror("[%s] can't get stats, link=%d", b->name, linkNum);
! 707: return -1;
! 708: }
! 709: if (statp != NULL)
! 710: memcpy(statp, u.reply.data, sizeof(*statp));
! 711: return(0);
! 712: }
! 713: #endif
! 714:
! 715: /*
! 716: * NgFuncErrx()
! 717: */
! 718:
! 719: void
! 720: NgFuncErrx(const char *fmt, ...)
! 721: {
! 722: char buf[100];
! 723: va_list args;
! 724:
! 725: va_start(args, fmt);
! 726: vsnprintf(buf, sizeof(buf), fmt, args);
! 727: va_end(args);
! 728: Log(LG_ERR, ("netgraph: %s", buf));
! 729: }
! 730:
! 731: /*
! 732: * NgFuncErr()
! 733: */
! 734:
! 735: void
! 736: NgFuncErr(const char *fmt, ...)
! 737: {
! 738: char buf[100];
! 739: va_list args;
! 740:
! 741: va_start(args, fmt);
! 742: vsnprintf(buf, sizeof(buf), fmt, args);
! 743: va_end(args);
! 744: Perror("netgraph: %s", buf);
! 745: }
! 746:
! 747: #ifdef USE_NG_NETFLOW
! 748: /*
! 749: * NetflowSetCommand()
! 750: */
! 751:
! 752: static int
! 753: NetflowSetCommand(Context ctx, int ac, char *av[], void *arg)
! 754: {
! 755: struct sockaddr_storage *sin;
! 756:
! 757: switch ((intptr_t)arg) {
! 758: case SET_PEER:
! 759: if (ac != 2)
! 760: return (-1);
! 761: if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
! 762: return (-1);
! 763: gNetflowExport = *sin;
! 764: break;
! 765: case SET_SELF:
! 766: if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
! 767: return (-1);
! 768: gNetflowSource = *sin;
! 769: break;
! 770: case SET_TIMEOUTS:
! 771: if (ac != 2)
! 772: return (-1);
! 773: if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
! 774: Error("Bad netflow timeouts \"%s %s\"", av[0], av[1]);
! 775: gNetflowInactive = atoi(av[0]);
! 776: gNetflowActive = atoi(av[1]);
! 777: break;
! 778: #if NGM_NETFLOW_COOKIE >= 1309868867
! 779: case SET_TEMPLATE:
! 780: if (ac != 2)
! 781: return (-1);
! 782: /*
! 783: * RFC 3954 clause 7.3
! 784: * "Both options MUST be configurable by the user on the Exporter."
! 785: */
! 786: if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
! 787: Error("Bad netflow v9 template values \"%s %s\"", av[0], av[1]);
! 788: gNetflowTime = atoi(av[0]); /* Default 600 */
! 789: gNetflowPackets = atoi(av[1]); /* Default 500 */
! 790: break;
! 791: case SET_MTU:
! 792: if (ac != 1)
! 793: return (-1);
! 794: if (atoi(av[0]) < MIN_MTU || atoi(av[0]) > MAX_MTU)
! 795: Error("Bad netflow v9 MTU \"%s\"", av[0]);
! 796: gNetflowMTU = atoi(av[0]); /* Default 1500 */
! 797: break;
! 798: case SET_VERSION:
! 799: if (ac != 1)
! 800: return (-1);
! 801: if (atoi(av[0]) != 5 && atoi(av[0]) != 9)
! 802: Error("Bad netflow export version \"%s\"", av[0]);
! 803: gNetflowVer = atoi(av[0]); /* Default 5 */
! 804: break;
! 805: #endif
! 806: case SET_NODE:
! 807: if (ac != 1)
! 808: return (-1);
! 809: if (strlen(av[0]) == 0 || strlen(av[0]) > 63)
! 810: Error("Bad netflow node name \"%s\"", av[0]);
! 811: strlcpy(gNetflowNodeName, av[0], sizeof(gNetflowNodeName));
! 812: gNetflowNode=TRUE;
! 813: gNetflowNodeShutdown=FALSE;
! 814: break;
! 815: case SET_HOOK:
! 816: if (ac != 1)
! 817: return (-1);
! 818: if (atoi(av[0]) <= 0)
! 819: Error("Bad netflow hook number \"%s\"", av[0]);
! 820: gNetflowIface = atoi(av[0])-1;
! 821: break;
! 822:
! 823: default:
! 824: return (-1);
! 825: }
! 826:
! 827: return (0);
! 828: }
! 829: #endif /* USE_NG_NETFLOW */
! 830:
! 831: ng_ID_t
! 832: NgGetNodeID(int csock, const char *path)
! 833: {
! 834: union {
! 835: u_char buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
! 836: struct ng_mesg reply;
! 837: } u;
! 838: struct nodeinfo *const ni = (struct nodeinfo *)(void *)u.reply.data;
! 839:
! 840: if (csock < 0) {
! 841: if (!gNgStatSock) {
! 842: char name[NG_NODESIZ];
! 843:
! 844: /* Create a netgraph socket node */
! 845: snprintf(name, sizeof(name), "mpd%d-stats", gPid);
! 846: if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
! 847: Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
! 848: return(-1);
! 849: }
! 850: (void) fcntl(gNgStatSock, F_SETFD, 1);
! 851: }
! 852: csock = gNgStatSock;
! 853: }
! 854:
! 855: if (NgSendMsg(csock, path,
! 856: NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0)
! 857: return (0);
! 858: if (NgRecvMsg(csock, &u.reply, sizeof(u), NULL) < 0)
! 859: return (0);
! 860:
! 861: return (ni->id);
! 862: }
! 863:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>