Annotation of embedaddon/mpd/src/ngfunc.c, revision 1.1.1.4
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: #include <netgraph/netflow/netflow.h>
1.1.1.2 misho 48: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1 misho 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
1.1.1.4 ! misho 85: static int NetflowSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 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 },
1.1.1.4 ! misho 112: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 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
1.1.1.4 ! misho 134: static uint16_t gNetflowTime = 0;
! 135: static uint16_t gNetflowPackets = 0;
! 136: static uint16_t gNetflowMTU = 0;
! 137: static u_int gNetflowVer = 5;
1.1 misho 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);
1.1.1.4 ! misho 163: if ((gNetflowNodeID = NgGetNodeID(csock, path)) == 0) {
! 164: Perror("NETFLOW: Cannot get %s node id", NG_NETFLOW_NODE_TYPE);
! 165: goto fail;
! 166: }
1.1 misho 167: close(csock);
168: return (0);
169: }
170:
171: snprintf(gNetflowNodeName, sizeof(gNetflowNodeName), "mpd%d-nf", gPid);
172:
173: /* Create a global netflow node. */
174: strcpy(mp.type, NG_NETFLOW_NODE_TYPE);
175: strcpy(mp.ourhook, TEMPHOOK);
176: strcpy(mp.peerhook, NG_NETFLOW_HOOK_DATA "0");
177: if (NgSendMsg(csock, ".:",
178: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
179: Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
180: mp.type, ".:", mp.ourhook);
181: goto fail;
182: }
183:
184: /* Get new node ID. */
1.1.1.4 ! misho 185: if ((gNetflowNodeID = NgGetNodeID(csock, TEMPHOOK)) == 0) {
! 186: Perror("NETFLOW: Cannot get %s node id", NG_NETFLOW_NODE_TYPE);
! 187: goto fail;
! 188: }
1.1 misho 189:
190: /* Set the new node's name. */
191: strcpy(nm.name, gNetflowNodeName);
192: if (NgSendMsg(csock, TEMPHOOK,
193: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
194: Perror("NETFLOW: Can't name %s node", NG_NETFLOW_NODE_TYPE);
195: goto fail;
196: }
197:
198: /* Connect ng_ksocket(4) node for export. */
199: strcpy(mp.type, NG_KSOCKET_NODE_TYPE);
200: #if NGM_NETFLOW_COOKIE >= 1309868867
201: if (gNetflowVer == 5) {
202: #endif
203: strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT);
204: #if NGM_NETFLOW_COOKIE >= 1309868867
205: } else {
206: strcpy(mp.ourhook, NG_NETFLOW_HOOK_EXPORT9);
207: }
208: #endif
209: if (gNetflowExport.ss_family==AF_INET6) {
210: snprintf(mp.peerhook, sizeof(mp.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
211: } else {
212: snprintf(mp.peerhook, sizeof(mp.peerhook), "inet/dgram/udp");
213: }
214: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
215: if (NgSendMsg(csock, path,
216: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
217: Perror("NETFLOW: Can't create %s node at \"%s\"->\"%s\"",
218: mp.type, path, mp.ourhook);
219: goto fail;
220: }
221:
222: /* Configure timeouts for ng_netflow(4). */
223: if (gNetflowInactive != 0 && gNetflowActive != 0) {
224: struct ng_netflow_settimeouts nf_settime;
225:
226: nf_settime.inactive_timeout = gNetflowInactive;
227: nf_settime.active_timeout = gNetflowActive;
228:
229: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
230: NGM_NETFLOW_SETTIMEOUTS, &nf_settime, sizeof(nf_settime)) < 0) {
231: Perror("NETFLOW: Can't set timeouts on netflow %s node",
232: NG_NETFLOW_NODE_TYPE);
233: goto fail2;
234: }
235: }
236:
237: #if NGM_NETFLOW_COOKIE >= 1309868867
238: if (gNetflowTime != 0 && gNetflowPackets != 0) {
239: struct ng_netflow_settemplate nf_settempl;
240:
241: nf_settempl.time = gNetflowTime;
242: nf_settempl.packets = gNetflowPackets;
243: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
244: NGM_NETFLOW_SETTEMPLATE, &nf_settempl, sizeof(nf_settempl)) < 0) {
245: Perror("NETFLOW: Can't set NetFlow v9 template on netflow %s node",
246: NG_NETFLOW_NODE_TYPE);
247: goto fail2;
248: }
249: }
250:
251: if (gNetflowMTU != 0) {
252: struct ng_netflow_setmtu nf_setmtu;
253:
254: nf_setmtu.mtu = gNetflowMTU;
255: if (NgSendMsg(csock, path, NGM_NETFLOW_COOKIE,
256: NGM_NETFLOW_SETMTU, &nf_setmtu, sizeof(nf_setmtu)) < 0) {
257: Perror("NETFLOW: Can't set NetFlow v9 MTU on netflow %s node",
258: NG_NETFLOW_NODE_TYPE);
259: goto fail2;
260: }
261: }
262: #endif
263:
264: /* Configure export destination and source on ng_ksocket(4). */
265: #if NGM_NETFLOW_COOKIE >= 1309868867
266: if (gNetflowVer == 5) {
267: #endif
268: strlcat(path, NG_NETFLOW_HOOK_EXPORT, sizeof(path));
269: #if NGM_NETFLOW_COOKIE >= 1309868867
270: } else {
271: strlcat(path, NG_NETFLOW_HOOK_EXPORT9, sizeof(path));
272: }
273: #endif
274: if (gNetflowSource.ss_len != 0) {
275: if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
276: NGM_KSOCKET_BIND, &gNetflowSource, sizeof(gNetflowSource)) < 0) {
277: Perror("NETFLOW: Can't bind export %s node", NG_KSOCKET_NODE_TYPE);
278: goto fail2;
279: }
280: }
281: if (gNetflowExport.ss_len != 0) {
282: if (NgSendMsg(csock, path, NGM_KSOCKET_COOKIE,
283: NGM_KSOCKET_CONNECT, &gNetflowExport, sizeof(gNetflowExport)) < 0) {
284: Perror("NETFLOW: Can't connect export %s node", NG_KSOCKET_NODE_TYPE);
285: goto fail2;
286: }
287: }
288:
289: /* Set the new node's name. */
290: snprintf(nm.name, sizeof(nm.name), "mpd%d-nfso", gPid);
291: if (NgSendMsg(csock, path,
292: NGM_GENERIC_COOKIE, NGM_NAME, &nm, sizeof(nm)) < 0) {
293: Perror("NETFLOW: Can't name %s node", NG_KSOCKET_NODE_TYPE);
294: goto fail2;
295: }
296:
297: /* Disconnect temporary hook. */
298: memset(&rm, 0, sizeof(rm));
299: strncpy(rm.ourhook, TEMPHOOK, sizeof(rm.ourhook));
300: if (NgSendMsg(csock, ".:",
301: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
302: Perror("can't remove hook %s", TEMPHOOK);
303: goto fail2;
304: }
305: gNetflowNode = TRUE;
306: close(csock);
307:
308: return (0);
309: fail2:
310: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
311: NgFuncShutdownNode(csock, "netflow", path);
312: fail:
313: gNetflowNodeID = 0;
314: close(csock);
315: return (-1);
316: }
317: #endif
318:
319: /*
320: * NgFuncCreateIface()
321: *
322: * Create a new netgraph interface.
323: */
324:
325: int
326: NgFuncCreateIface(Bund b, char *buf, int max)
327: {
328: union {
329: u_char buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
330: struct ng_mesg reply;
331: } u;
332: struct nodeinfo *const ni = (struct nodeinfo *)(void *)u.reply.data;
333: struct ngm_rmhook rm;
334: struct ngm_mkpeer mp;
335: int rtn = 0;
336:
337: /* Create iface node (as a temporary peer of the socket node) */
338: strcpy(mp.type, NG_IFACE_NODE_TYPE);
339: strcpy(mp.ourhook, TEMPHOOK);
340: strcpy(mp.peerhook, NG_IFACE_HOOK_INET);
341: if (NgSendMsg(gLinksCsock, ".:",
342: NGM_GENERIC_COOKIE, NGM_MKPEER, &mp, sizeof(mp)) < 0) {
343: Log(LG_ERR, ("[%s] can't create %s node at \"%s\"->\"%s\": %s %d",
344: b->name, NG_IFACE_NODE_TYPE, ".:", mp.ourhook, strerror(errno), gLinksCsock));
345: return(-1);
346: }
347:
348: /* Get the new node's name */
349: if (NgSendMsg(gLinksCsock, TEMPHOOK,
350: NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
351: Perror("[%s] %s", b->name, "NGM_NODEINFO");
352: rtn = -1;
353: goto done;
354: }
355: if (NgRecvMsg(gLinksCsock, &u.reply, sizeof(u), NULL) < 0) {
356: Perror("[%s] reply from %s", b->name, NG_IFACE_NODE_TYPE);
357: rtn = -1;
358: goto done;
359: }
360: strlcpy(buf, ni->name, max);
361:
362: done:
363: /* Disconnect temporary hook */
364: strcpy(rm.ourhook, TEMPHOOK);
365: if (NgSendMsg(gLinksCsock, ".:",
366: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
367: Perror("[%s] can't remove hook %s", b->name, TEMPHOOK);
368: rtn = -1;
369: }
370:
371: /* Done */
372: return(rtn);
373: }
374:
375: /*
376: * NgFuncShutdownGlobal()
377: *
378: * Shutdown nodes, that are shared between bundles.
379: */
380:
381: void
382: NgFuncShutdownGlobal(void)
383: {
384: #ifdef USE_NG_NETFLOW
385: char path[NG_PATHSIZ];
386: int csock;
387:
388: if (gNetflowNode == FALSE || gNetflowNodeShutdown==FALSE)
389: return;
390:
391: /* Create a netgraph socket node */
392: if (NgMkSockNode(NULL, &csock, NULL) < 0) {
393: Perror("NgFuncShutdownGlobal: can't create %s node", NG_SOCKET_NODE_TYPE);
394: return;
395: }
396:
397: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
398: NgFuncShutdownNode(csock, "netflow", path);
399:
400: close(csock);
401: #endif
402: }
403:
404: /*
405: * NgFuncShutdownNode()
406: */
407:
408: int
409: NgFuncShutdownNode(int csock, const char *label, const char *path)
410: {
411: int rtn, retry = 10, delay = 1000;
412:
413: retry:
414: if ((rtn = NgSendMsg(csock, path,
415: NGM_GENERIC_COOKIE, NGM_SHUTDOWN, NULL, 0)) < 0) {
416: if (errno == ENOBUFS && retry > 0) {
417: Log(LG_ERR, ("[%s] shutdown \"%s\": %s, retrying...",
418: label, path, strerror(errno)));
419: usleep(delay);
420: retry--;
421: delay *= 2;
422: goto retry;
423: }
424: if (errno != ENOENT) {
425: Perror("[%s] can't shutdown \"%s\"", label, path);
426: }
427: }
428: return(rtn);
429: }
430:
431: /*
432: * NgFuncSetConfig()
433: */
434:
435: void
436: NgFuncSetConfig(Bund b)
437: {
438: char path[NG_PATHSIZ];
439: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
440: if (NgSendMsg(gLinksCsock, path, NGM_PPP_COOKIE,
441: NGM_PPP_SET_CONFIG, &b->pppConfig, sizeof(b->pppConfig)) < 0) {
442: Perror("[%s] can't config %s", b->name, path);
443: DoExit(EX_ERRDEAD);
444: }
445: }
446:
447: /*
448: * NgFuncSendQuery()
449: */
450:
451: int
452: NgFuncSendQuery(const char *path, int cookie, int cmd, const void *args,
453: size_t arglen, struct ng_mesg *rbuf, size_t replen, char *raddr)
454: {
455:
456: if (!gNgStatSock) {
457: char name[NG_NODESIZ];
458:
459: /* Create a netgraph socket node */
460: snprintf(name, sizeof(name), "mpd%d-stats", gPid);
461: if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
462: Perror("NgFuncSendQuery: can't create %s node", NG_SOCKET_NODE_TYPE);
463: return(-1);
464: }
465: (void) fcntl(gNgStatSock, F_SETFD, 1);
466: }
467:
468: /* Send message */
1.1.1.2 misho 469: if (NgSendMsg(gNgStatSock, path, cookie, cmd, args, arglen) < 0) {
470: Perror("NgFuncSendQuery: can't send message");
1.1 misho 471: return (-1);
1.1.1.2 misho 472: }
1.1 misho 473:
474: /* Read message */
475: if (NgRecvMsg(gNgStatSock, rbuf, replen, raddr) < 0) {
476: Perror("NgFuncSendQuery: can't read unexpected message");
477: return (-1);
478: }
479:
480: return (0);
481: }
482:
483: /*
484: * NgFuncConnect()
485: */
486:
487: int
488: NgFuncConnect(int csock, char *label, const char *path, const char *hook,
489: const char *path2, const char *hook2)
490: {
491: struct ngm_connect cn;
492:
493: strlcpy(cn.path, path2, sizeof(cn.path));
494: strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
495: strlcpy(cn.peerhook, hook2, sizeof(cn.peerhook));
496: if (NgSendMsg(csock, path,
497: NGM_GENERIC_COOKIE, NGM_CONNECT, &cn, sizeof(cn)) < 0) {
498: Perror("[%s] can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
499: label, path, hook, path2, hook2);
500: return(-1);
501: }
502: return(0);
503: }
504:
505: /*
506: * NgFuncDisconnect()
507: */
508:
509: int
510: NgFuncDisconnect(int csock, char *label, const char *path, const char *hook)
511: {
512: struct ngm_rmhook rm;
513: int retry = 10, delay = 1000;
514:
515: /* Disconnect hook */
516: memset(&rm, 0, sizeof(rm));
517: strlcpy(rm.ourhook, hook, sizeof(rm.ourhook));
518: retry:
519: if (NgSendMsg(csock, path,
520: NGM_GENERIC_COOKIE, NGM_RMHOOK, &rm, sizeof(rm)) < 0) {
521: if (errno == ENOBUFS && retry > 0) {
522: Log(LG_ERR, ("[%s] remove hook %s from node \"%s\": %s, retrying...",
523: label, hook, path, strerror(errno)));
524: usleep(delay);
525: retry--;
526: delay *= 2;
527: goto retry;
528: }
529: Perror("[%s] can't remove hook %s from node \"%s\"", label, hook, path);
530: return(-1);
531: }
532: return(0);
533: }
534:
535: /*
536: * NgFuncWritePppFrame()
537: *
538: * Consumes the mbuf.
539: */
540:
541: int
542: NgFuncWritePppFrame(Bund b, int linkNum, int proto, Mbuf bp)
543: {
544: u_int16_t temp;
545:
546: /* Prepend ppp node bypass header */
547: temp = htons(linkNum);
548: bp = mbcopyback(bp, -4, &temp, 2);
549: temp = htons(proto);
550: bp = mbcopyback(bp, 2, &temp, 2);
551:
552: /* Debugging */
553: LogDumpBp(LG_FRAME, bp,
554: "[%s] xmit bypass frame link=%d proto=0x%04x",
555: b->name, (int16_t)linkNum, proto);
556:
557: if ((linkNum == NG_PPP_BUNDLE_LINKNUM && b->n_up == 0) ||
558: (linkNum != NG_PPP_BUNDLE_LINKNUM &&
559: (b->links[linkNum] == NULL ||
560: b->links[linkNum]->state != PHYS_STATE_UP))) {
561: Log(LG_FRAME, ("[%s] Bundle: No links ready to send packet", b->name));
562: mbfree(bp);
563: return (-1);
564: }
565:
566: /* Write frame */
567: return NgFuncWriteFrame(gLinksDsock, b->hook, b->name, bp);
568: }
569:
570: /*
571: * NgFuncWritePppFrameLink()
572: *
573: * Consumes the mbuf.
574: */
575:
576: int
577: NgFuncWritePppFrameLink(Link l, int proto, Mbuf bp)
578: {
579: u_int16_t temp;
580:
581: if (l->joined_bund) {
582: return (NgFuncWritePppFrame(l->bund, l->bundleIndex, proto, bp));
583: }
584:
585: /* Prepend framing */
586: temp = htons(0xff03);
587: bp = mbcopyback(bp, -4, &temp, 2);
588: temp = htons(proto);
589: bp = mbcopyback(bp, 2, &temp, 2);
590:
591: /* Debugging */
592: LogDumpBp(LG_FRAME, bp,
593: "[%s] xmit frame to link proto=0x%04x",
594: l->name, proto);
595:
596: if (l->state != PHYS_STATE_UP) {
597: Log(LG_FRAME, ("[%s] Link: Not ready to send packet", l->name));
598: mbfree(bp);
599: return (-1);
600: }
601:
602: /* Write frame */
603: return NgFuncWriteFrame(gLinksDsock, l->hook, l->name, bp);
604: }
605:
606: /*
607: * NgFuncWriteFrame()
608: *
609: * Consumes the mbuf.
610: */
611:
612: int
613: NgFuncWriteFrame(int dsock, const char *hookname, const char *label, Mbuf bp)
614: {
615: union {
616: u_char buf[sizeof(struct sockaddr_ng) + NG_HOOKSIZ];
617: struct sockaddr_ng sa_ng;
618: } u;
619: struct sockaddr_ng *ng = &u.sa_ng;
620: int rtn;
621:
622: /* Write frame */
623: if (bp == NULL)
624: return (-1);
625:
626: /* Set dest address */
627: memset(&u.buf, 0, sizeof(u.buf));
628: strlcpy(ng->sg_data, hookname, NG_HOOKSIZ);
629: ng->sg_family = AF_NETGRAPH;
630: ng->sg_len = 3 + strlen(ng->sg_data);
631:
632: rtn = sendto(dsock, MBDATAU(bp), MBLEN(bp),
633: 0, (struct sockaddr *)ng, ng->sg_len);
634:
635: /* ENOBUFS can be expected on some links, e.g., ng_pptpgre(4) */
636: if (rtn < 0 && errno != ENOBUFS) {
637: Perror("[%s] error writing len %d frame to %s",
1.1.1.3 misho 638: label, (int)MBLEN(bp), hookname);
1.1 misho 639: }
640: mbfree(bp);
641: return (rtn);
642: }
643:
644: /*
645: * NgFuncClrStats()
646: *
647: * Clear link or whole bundle statistics
648: */
649:
650: int
651: NgFuncClrStats(Bund b, u_int16_t linkNum)
652: {
653: char path[NG_PATHSIZ];
654:
655: /* Get stats */
656: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
657: if (NgSendMsg(gLinksCsock, path,
658: NGM_PPP_COOKIE, NGM_PPP_CLR_LINK_STATS, &linkNum, sizeof(linkNum)) < 0) {
659: Perror("[%s] can't clear stats, link=%d", b->name, linkNum);
660: return (-1);
661: }
662: return(0);
663: }
664:
1.1.1.4 ! misho 665: #ifndef NG_PPP_STATS64
! 666:
1.1 misho 667: /*
668: * NgFuncGetStats()
669: *
670: * Get link or whole bundle statistics
671: */
672:
673: int
674: NgFuncGetStats(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat *statp)
675: {
676: union {
677: u_char buf[sizeof(struct ng_mesg)
678: + sizeof(struct ng_ppp_link_stat)];
679: struct ng_mesg reply;
680: } u;
681: char path[NG_PATHSIZ];
682:
683: /* Get stats */
684: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
685: if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS,
686: &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
687: Perror("[%s] can't get stats, link=%d", b->name, linkNum);
688: return -1;
689: }
690: if (statp != NULL)
691: memcpy(statp, u.reply.data, sizeof(*statp));
692: return(0);
693: }
694:
1.1.1.4 ! misho 695: #else
1.1 misho 696: /*
697: * NgFuncGetStats64()
698: *
699: * Get 64bit link or whole bundle statistics
700: */
701:
702: int
703: NgFuncGetStats64(Bund b, u_int16_t linkNum, struct ng_ppp_link_stat64 *statp)
704: {
705: union {
706: u_char buf[sizeof(struct ng_mesg)
707: + sizeof(struct ng_ppp_link_stat64)];
708: struct ng_mesg reply;
709: } u;
710: char path[NG_PATHSIZ];
711:
712: /* Get stats */
713: snprintf(path, sizeof(path), "[%x]:", b->nodeID);
714: if (NgFuncSendQuery(path, NGM_PPP_COOKIE, NGM_PPP_GET_LINK_STATS64,
715: &linkNum, sizeof(linkNum), &u.reply, sizeof(u), NULL) < 0) {
716: Perror("[%s] can't get stats, link=%d", b->name, linkNum);
717: return -1;
718: }
719: if (statp != NULL)
720: memcpy(statp, u.reply.data, sizeof(*statp));
721: return(0);
722: }
723: #endif
724:
725: /*
726: * NgFuncErrx()
727: */
728:
729: void
730: NgFuncErrx(const char *fmt, ...)
731: {
732: char buf[100];
733: va_list args;
734:
735: va_start(args, fmt);
736: vsnprintf(buf, sizeof(buf), fmt, args);
737: va_end(args);
738: Log(LG_ERR, ("netgraph: %s", buf));
739: }
740:
741: /*
742: * NgFuncErr()
743: */
744:
745: void
746: NgFuncErr(const char *fmt, ...)
747: {
748: char buf[100];
749: va_list args;
750:
751: va_start(args, fmt);
752: vsnprintf(buf, sizeof(buf), fmt, args);
753: va_end(args);
754: Perror("netgraph: %s", buf);
755: }
756:
757: #ifdef USE_NG_NETFLOW
758: /*
759: * NetflowSetCommand()
760: */
761:
762: static int
1.1.1.4 ! misho 763: NetflowSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 764: {
765: struct sockaddr_storage *sin;
766:
767: switch ((intptr_t)arg) {
768: case SET_PEER:
769: if (ac != 2)
770: return (-1);
771: if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
772: return (-1);
773: gNetflowExport = *sin;
774: break;
775: case SET_SELF:
1.1.1.3 misho 776: if (ac != 1 && ac != 2)
777: return (-1);
1.1 misho 778: if ((sin = ParseAddrPort(ac, av, ALLOW_IPV4|ALLOW_IPV6)) == NULL)
779: return (-1);
780: gNetflowSource = *sin;
781: break;
782: case SET_TIMEOUTS:
783: if (ac != 2)
784: return (-1);
785: if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
786: Error("Bad netflow timeouts \"%s %s\"", av[0], av[1]);
787: gNetflowInactive = atoi(av[0]);
788: gNetflowActive = atoi(av[1]);
789: break;
790: #if NGM_NETFLOW_COOKIE >= 1309868867
791: case SET_TEMPLATE:
792: if (ac != 2)
793: return (-1);
794: /*
795: * RFC 3954 clause 7.3
796: * "Both options MUST be configurable by the user on the Exporter."
797: */
798: if (atoi(av[0]) <= 0 || atoi(av[1]) <= 0)
799: Error("Bad netflow v9 template values \"%s %s\"", av[0], av[1]);
800: gNetflowTime = atoi(av[0]); /* Default 600 */
801: gNetflowPackets = atoi(av[1]); /* Default 500 */
802: break;
803: case SET_MTU:
804: if (ac != 1)
805: return (-1);
1.1.1.4 ! misho 806: if (atoi(av[0]) < (int)MIN_MTU || atoi(av[0]) > (int)MAX_MTU)
1.1 misho 807: Error("Bad netflow v9 MTU \"%s\"", av[0]);
808: gNetflowMTU = atoi(av[0]); /* Default 1500 */
809: break;
810: case SET_VERSION:
811: if (ac != 1)
812: return (-1);
813: if (atoi(av[0]) != 5 && atoi(av[0]) != 9)
814: Error("Bad netflow export version \"%s\"", av[0]);
815: gNetflowVer = atoi(av[0]); /* Default 5 */
816: break;
817: #endif
818: case SET_NODE:
819: if (ac != 1)
820: return (-1);
821: if (strlen(av[0]) == 0 || strlen(av[0]) > 63)
822: Error("Bad netflow node name \"%s\"", av[0]);
823: strlcpy(gNetflowNodeName, av[0], sizeof(gNetflowNodeName));
824: gNetflowNode=TRUE;
825: gNetflowNodeShutdown=FALSE;
826: break;
827: case SET_HOOK:
828: if (ac != 1)
829: return (-1);
1.1.1.3 misho 830: if (atoi(av[0]) <= 0 || atoi(av[0]) >= NG_NETFLOW_MAXIFACES)
1.1 misho 831: Error("Bad netflow hook number \"%s\"", av[0]);
832: gNetflowIface = atoi(av[0])-1;
833: break;
834:
835: default:
836: return (-1);
837: }
838:
839: return (0);
840: }
1.1.1.2 misho 841:
842: /*
843: * ShowNetflow()
844: *
845: * Show state of a Netflow
846: */
847:
848: int
1.1.1.4 ! misho 849: ShowNetflow(Context ctx, int ac, const char *const av[], const void *arg)
1.1.1.2 misho 850: {
851: struct u_addr addr;
852: in_port_t port;
853: char buf[64];
854: char path[NG_PATHSIZ];
855: union {
856: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_netflow_info)];
857: struct ng_mesg reply;
858: } u;
859: struct ng_netflow_info *const ni = \
860: (struct ng_netflow_info *)(void *)u.reply.data;
861: #ifdef NGM_NETFLOW_V9_COOKIE
862: union {
863: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ng_netflow_v9info)];
864: struct ng_mesg reply;
865: } uv9;
866: struct ng_netflow_v9info *const niv9 = \
867: (struct ng_netflow_v9info *)(void *)uv9.reply.data;
868: #endif /* NGM_NETFLOW_V9_COOKIE */
869:
1.1.1.4 ! misho 870: (void)ac;
! 871: (void)av;
! 872: (void)arg;
! 873:
1.1.1.2 misho 874: if (gNetflowNodeID>0) {
875: snprintf(path, sizeof(path), "[%x]:", gNetflowNodeID);
876: if (NgFuncSendQuery(path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_INFO,
877: NULL, 0, &u.reply, sizeof(u), NULL) < 0)
878: return(-7);
879: #ifdef NGM_NETFLOW_V9_COOKIE
880: if (NgFuncSendQuery(path, NGM_NETFLOW_COOKIE, NGM_NETFLOW_V9INFO,
881: NULL, 0, &uv9.reply, sizeof(uv9), NULL) < 0)
882: return(-7);
883: #endif /* NGM_NETFLOW_V9_COOKIE */
884: }
885:
886: Printf("Netflow status:\r\n");
887: Printf("\tNode created : %s\r\n", gNetflowNodeID ? "Yes" : "No");
888: Printf("Netflow settings:\r\n");
889: Printf("\tNode name : %s\r\n", gNetflowNodeName);
890: Printf("\tInitial hook : %d\r\n", gNetflowIface);
891: Printf("\tTimeouts, sec:\r\n");
1.1.1.3 misho 892: Printf("\t Active : %u\r\n",
1.1.1.2 misho 893: (gNetflowNodeID>0) ? ni->nfinfo_act_t :
894: (gNetflowActive ? gNetflowActive : ACTIVE_TIMEOUT));
1.1.1.3 misho 895: Printf("\t Inactive : %u\r\n",
1.1.1.2 misho 896: (gNetflowNodeID>0) ? ni->nfinfo_inact_t :
897: (gNetflowInactive ? gNetflowInactive : INACTIVE_TIMEOUT));
898: sockaddrtou_addr(&gNetflowExport, &addr, &port);
899: Printf("\tExport address : %s port %d\r\n",
900: u_addrtoa(&addr, buf, sizeof(buf)), (int)port);
901: sockaddrtou_addr(&gNetflowSource, &addr, &port);
902: Printf("\tSource address : %s port %d\r\n",
903: u_addrtoa(&addr, buf, sizeof(buf)), (int)port);
904: #if NGM_NETFLOW_COOKIE >= 1309868867
905: Printf("\tExport version : v%d\r\n", gNetflowVer);
906: Printf("Netflow v9 configuration:\r\n");
907: Printf("\tTemplate:\r\n");
908: #ifdef NGM_NETFLOW_V9_COOKIE
909: Printf("\t Time : %d\r\n",
910: (gNetflowNodeID>0) ? niv9->templ_time :
911: (gNetflowTime ? gNetflowTime : NETFLOW_V9_MAX_TIME_TEMPL));
912: Printf("\t Packets : %d\r\n",
913: (gNetflowNodeID>0) ? niv9->templ_packets :
914: (gNetflowPackets ? gNetflowPackets : NETFLOW_V9_MAX_PACKETS_TEMPL));
915: Printf("\tNetflow v9 MTU : %d\r\n",
916: (gNetflowNodeID>0) ? niv9->mtu :
917: (gNetflowMTU ? gNetflowMTU : BASE_MTU));
918: #else
919: Printf("\t Time : %d\r\n",
920: gNetflowTime ? gNetflowTime : NETFLOW_V9_MAX_TIME_TEMPL);
921: Printf("\t Packets : %d\r\n",
922: gNetflowPackets ? gNetflowPackets : NETFLOW_V9_MAX_PACKETS_TEMPL);
923: Printf("\tNetflow v9 MTU : %d\r\n",
924: gNetflowMTU ? gNetflowMTU : BASE_MTU);
925: #endif /* NGM_NETFLOW_V9_COOKIE */
926: #endif
927: if (gNetflowNodeID>0) {
928: Printf("Traffic stats:\r\n");
1.1.1.3 misho 929: #if NGM_NETFLOW_COOKIE >= 1365756954
930: Printf("\tAccounted IPv4 octets : %llu\r\n", (unsigned long long)ni->nfinfo_bytes);
931: Printf("\tAccounted IPv4 packets : %llu\r\n", (unsigned long long)ni->nfinfo_packets);
932: Printf("\tAccounted IPv6 octets : %llu\r\n", (unsigned long long)ni->nfinfo_bytes6);
933: Printf("\tAccounted IPv6 packets : %llu\r\n", (unsigned long long)ni->nfinfo_packets6);
934: Printf("\tSkipped IPv4 octets : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes);
935: Printf("\tSkipped IPv4 packets : %llu\r\n", (unsigned long long)ni->nfinfo_spackets);
936: Printf("\tSkipped IPv6 octets : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes6);
937: Printf("\tSkipped IPv6 packets : %llu\r\n", (unsigned long long)ni->nfinfo_spackets6);
938: Printf("\tActive expiries : %llu\r\n", (unsigned long long)ni->nfinfo_act_exp);
939: Printf("\tInactive expiries : %llu\r\n", (unsigned long long)ni->nfinfo_inact_exp);
940: Printf("\tUsed IPv4 cache records: %u\r\n", ni->nfinfo_used);
941: Printf("\tUsed IPv6 cache records: %u\r\n", ni->nfinfo_used6);
942: Printf("\tFailed allocations : %u\r\n", ni->nfinfo_alloc_failed);
943: Printf("\tFailed v5 export : %u\r\n", ni->nfinfo_export_failed);
944: Printf("\tFailed v9 export : %u\r\n", ni->nfinfo_export9_failed);
945: Printf("\tRallocated mbufs : %u\r\n", ni->nfinfo_realloc_mbuf);
946: Printf("\tFibs allocated : %u\r\n", ni->nfinfo_alloc_fibs);
947: #else /* NGM_NETFLOW_COOKIE >= 1365756954 */
1.1.1.2 misho 948: Printf("\tAccounted IPv4 octets : %llu\r\n", (unsigned long long)ni->nfinfo_bytes);
1.1.1.3 misho 949: Printf("\tAccounted IPv4 packets : %u\r\n", ni->nfinfo_packets);
1.1.1.2 misho 950: #if NGM_NETFLOW_COOKIE >= 1309868867
951: Printf("\tAccounted IPv6 octets : %llu\r\n", (unsigned long long)ni->nfinfo_bytes6);
1.1.1.3 misho 952: Printf("\tAccounted IPv6 packets : %u\r\n", ni->nfinfo_packets6);
1.1.1.2 misho 953: Printf("\tSkipped IPv4 octets : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes);
1.1.1.3 misho 954: Printf("\tSkipped IPv4 packets : %u\r\n", ni->nfinfo_spackets);
1.1.1.2 misho 955: Printf("\tSkipped IPv6 octets : %llu\r\n", (unsigned long long)ni->nfinfo_sbytes6);
1.1.1.3 misho 956: Printf("\tSkipped IPv6 packets : %u\r\n", ni->nfinfo_spackets6);
1.1.1.2 misho 957: #endif
1.1.1.3 misho 958: Printf("\tUsed IPv4 cache records: %u\r\n", ni->nfinfo_used);
1.1.1.2 misho 959: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1.1.3 misho 960: Printf("\tUsed IPv6 cache records: %u\r\n", ni->nfinfo_used6);
1.1.1.2 misho 961: #endif
1.1.1.3 misho 962: Printf("\tFailed allocations : %u\r\n", ni->nfinfo_alloc_failed);
963: Printf("\tFailed v5 export : %u\r\n", ni->nfinfo_export_failed);
1.1.1.2 misho 964: #if NGM_NETFLOW_COOKIE >= 1309868867
1.1.1.3 misho 965: Printf("\tFailed v9 export : %u\r\n", ni->nfinfo_export9_failed);
966: Printf("\tRallocated mbufs : %u\r\n", ni->nfinfo_realloc_mbuf);
967: Printf("\tFibs allocated : %u\r\n", ni->nfinfo_alloc_fibs);
1.1.1.2 misho 968: #endif
1.1.1.3 misho 969: Printf("\tActive expiries : %u\r\n", ni->nfinfo_act_exp);
970: Printf("\tInactive expiries : %u\r\n", ni->nfinfo_inact_exp);
971: #endif /* NGM_NETFLOW_COOKIE >= 1365756954 */
1.1.1.2 misho 972: }
973: return(0);
974: }
1.1 misho 975: #endif /* USE_NG_NETFLOW */
976:
977: ng_ID_t
978: NgGetNodeID(int csock, const char *path)
979: {
980: union {
981: u_char buf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
982: struct ng_mesg reply;
983: } u;
984: struct nodeinfo *const ni = (struct nodeinfo *)(void *)u.reply.data;
985:
986: if (csock < 0) {
987: if (!gNgStatSock) {
988: char name[NG_NODESIZ];
989:
990: /* Create a netgraph socket node */
991: snprintf(name, sizeof(name), "mpd%d-stats", gPid);
992: if (NgMkSockNode(name, &gNgStatSock, NULL) < 0) {
1.1.1.4 ! misho 993: Perror("NgMkSockNode: can't create %s node",
! 994: NG_SOCKET_NODE_TYPE);
! 995: return (0);
1.1 misho 996: }
997: (void) fcntl(gNgStatSock, F_SETFD, 1);
998: }
999: csock = gNgStatSock;
1000: }
1001:
1002: if (NgSendMsg(csock, path,
1.1.1.4 ! misho 1003: NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0) {
! 1004: Perror("NgSendMsg to %s", path);
1.1 misho 1005: return (0);
1.1.1.4 ! misho 1006: }
! 1007: if (NgRecvMsg(csock, &u.reply, sizeof(u), NULL) < 0) {
! 1008: Perror("NgRecvMsg from %s", path);
! 1009: return (0);
! 1010: }
! 1011:
1.1 misho 1012: return (ni->id);
1013: }
1014:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>