diff options
author | julian <julian@FreeBSD.org> | 1999-10-21 09:06:11 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1999-10-21 09:06:11 +0000 |
commit | c5c63975d538cf48ceb99ba48c341293676d15c0 (patch) | |
tree | 722c03ee4d750dd89ed43b028c35302fbfd03bfd /lib/libnetgraph | |
parent | 028ec91c46f181b4be2318c3bba8d194b5583f87 (diff) | |
download | FreeBSD-src-c5c63975d538cf48ceb99ba48c341293676d15c0.zip FreeBSD-src-c5c63975d538cf48ceb99ba48c341293676d15c0.tar.gz |
Whistle's Netgraph link-layer (sometimes more) networking infrastructure.
Been in production for 3 years now. Gives Instant Frame relay to if_sr
and if_ar drivers, and PPPOE support soon. See:
ftp://ftp.whistle.com/pub/archie/netgraph/index.html
for on-line manual pages.
Reviewed by: Doug Rabson (dfr@freebsd.org)
Obtained from: Whistle CVS tree
Diffstat (limited to 'lib/libnetgraph')
-rw-r--r-- | lib/libnetgraph/Makefile | 19 | ||||
-rw-r--r-- | lib/libnetgraph/debug.c | 404 | ||||
-rw-r--r-- | lib/libnetgraph/internal.h | 67 | ||||
-rw-r--r-- | lib/libnetgraph/msg.c | 206 | ||||
-rw-r--r-- | lib/libnetgraph/netgraph.3 | 211 | ||||
-rw-r--r-- | lib/libnetgraph/netgraph.h | 64 | ||||
-rw-r--r-- | lib/libnetgraph/sock.c | 264 |
7 files changed, 1235 insertions, 0 deletions
diff --git a/lib/libnetgraph/Makefile b/lib/libnetgraph/Makefile new file mode 100644 index 0000000..569a1f7 --- /dev/null +++ b/lib/libnetgraph/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ +# $Whistle: Makefile,v 1.4 1999/01/17 03:41:02 julian Exp $ + +LIB= netgraph +MAN3= netgraph.3 + +SHLIB_MAJOR= 1 +#SHLIB_MINOR= 1 + +SRCS= sock.c msg.c debug.c + +CFLAGS+= -g -Wall -O2 -Werror +CFLAGS+= -I/usr/src.freefall/sys + +beforeinstall: + ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/netgraph.h \ + ${DESTDIR}/usr/include + +.include <bsd.lib.mk> diff --git a/lib/libnetgraph/debug.c b/lib/libnetgraph/debug.c new file mode 100644 index 0000000..cdfb77e --- /dev/null +++ b/lib/libnetgraph/debug.c @@ -0,0 +1,404 @@ + +/* + * debug.c + * + * Copyright (c) 1996-1999 Whistle Communications, Inc. + * All rights reserved. + * + * Subject to the following obligations and disclaimer of warranty, use and + * redistribution of this software, in source or object code forms, with or + * without modifications are expressly permitted by Whistle Communications; + * provided, however, that: + * 1. Any and all reproductions of the source or object code must include the + * copyright notice above and the following disclaimer of warranties; and + * 2. No rights are granted, in any manner or form, to use Whistle + * Communications, Inc. trademarks, including the mark "WHISTLE + * COMMUNICATIONS" on advertising, endorsements, or otherwise except as + * such appears in the above copyright notice or in the software. + * + * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY + * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS + * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. + * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES + * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING + * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Archie Cobbs <archie@whistle.com> + * + * $FreeBSD$ + * $Whistle: debug.c,v 1.24 1999/01/24 01:15:33 archie Exp $ + */ + +#include <sys/types.h> +#include <stdarg.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_socket.h> + +#include "netgraph.h" +#include "internal.h" + +#include <netgraph/ng_socket.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_iface.h> +#include <netgraph/ng_rfc1490.h> +#include <netgraph/ng_cisco.h> +#include <netgraph/ng_async.h> +#include <netgraph/ng_ppp.h> +#include <netgraph/ng_frame_relay.h> +#include <netgraph/ng_lmi.h> +#include <netgraph/ng_tty.h> +#include <netgraph/ng_tty.h> + +/* Global debug level */ +int _gNgDebugLevel = 0; + +/* Debug printing functions */ +void (*_NgLog) (const char *fmt,...) = warn; +void (*_NgLogx) (const char *fmt,...) = warnx; + +/* Internal functions */ +static const char *NgCookie(int cookie); +static const char *NgCmd(int cookie, int cmd); +static void NgArgs(int cookie, int cmd, int resp, void *args, int arglen); + +/* + * Set debug level, ie, verbosity, if "level" is non-negative. + * Returns old debug level. + */ +int +NgSetDebug(int level) +{ + int old = _gNgDebugLevel; + + if (level < 0) + level = old; + _gNgDebugLevel = level; + return (old); +} + +/* + * Set debug logging functions. + */ +void +NgSetErrLog(void (*log) (const char *fmt,...), + void (*logx) (const char *fmt,...)) +{ + _NgLog = log; + _NgLogx = logx; +} + +/* + * Display a netgraph sockaddr + */ +void +_NgDebugSockaddr(struct sockaddr_ng *sg) +{ + NGLOGX("SOCKADDR: { fam=%d len=%d addr=\"%s\" }", + sg->sg_family, sg->sg_len, sg->sg_data); +} + +/* + * Display a negraph message + */ +void +_NgDebugMsg(struct ng_mesg * msg) +{ + NGLOGX("NG_MESG :"); + NGLOGX(" vers %d", msg->header.version); + NGLOGX(" arglen %d", msg->header.arglen); + NGLOGX(" flags %ld", msg->header.flags); + NGLOGX(" token %lu", (u_long) msg->header.token); + NGLOGX(" cookie %s", NgCookie(msg->header.typecookie)); + NGLOGX(" cmd %s", NgCmd(msg->header.typecookie, msg->header.cmd)); + NgArgs(msg->header.typecookie, msg->header.cmd, + (msg->header.flags & NGF_RESP), msg->data, msg->header.arglen); +} + +/* + * Return the name of the node type corresponding to the cookie + */ +static const char * +NgCookie(int cookie) +{ + static char buf[20]; + + switch (cookie) { + case NGM_GENERIC_COOKIE: + return "generic"; + case NGM_TTY_COOKIE: + return "tty"; + case NGM_ASYNC_COOKIE: + return "async"; + case NGM_IFACE_COOKIE: + return "iface"; + case NGM_FRAMERELAY_COOKIE: + return "frame_relay"; + case NGM_LMI_COOKIE: + return "lmi"; + case NGM_CISCO_COOKIE: + return "cisco"; + case NGM_PPP_COOKIE: + return "ppp"; + case NGM_RFC1490_NODE_COOKIE: + return "rfc1490"; + case NGM_SOCKET_COOKIE: + return "socket"; + } + snprintf(buf, sizeof(buf), "?? (%d)", cookie); + return buf; +} + +/* + * Return the name of the command + */ +static const char * +NgCmd(int cookie, int cmd) +{ + static char buf[20]; + + switch (cookie) { + case NGM_GENERIC_COOKIE: + switch (cmd) { + case NGM_SHUTDOWN: + return "shutdown"; + case NGM_MKPEER: + return "mkpeer"; + case NGM_CONNECT: + return "connect"; + case NGM_NAME: + return "name"; + case NGM_RMHOOK: + return "rmhook"; + case NGM_NODEINFO: + return "nodeinfo"; + case NGM_LISTHOOKS: + return "listhooks"; + case NGM_LISTNAMES: + return "listnames"; + case NGM_LISTNODES: + return "listnodes"; + case NGM_TEXT_STATUS: + return "text_status"; + } + break; + case NGM_TTY_COOKIE: + switch (cmd) { + case NGM_TTY_GET_HOTCHAR: + return "getHotChar"; + case NGM_TTY_SET_HOTCHAR: + return "setHotChar"; + } + break; + case NGM_ASYNC_COOKIE: + switch (cmd) { + case NGM_ASYNC_CMD_GET_STATS: + return "getStats"; + case NGM_ASYNC_CMD_CLR_STATS: + return "setStats"; + case NGM_ASYNC_CMD_SET_CONFIG: + return "setConfig"; + case NGM_ASYNC_CMD_GET_CONFIG: + return "getConfig"; + } + break; + case NGM_IFACE_COOKIE: + switch (cmd) { + case NGM_IFACE_GET_IFNAME: + return "getIfName"; + case NGM_IFACE_GET_IFADDRS: + return "getIfAddrs"; + } + break; + case NGM_LMI_COOKIE: + switch (cmd) { + case NGM_LMI_GET_STATUS: + return "get-status"; + } + break; + } + snprintf(buf, sizeof(buf), "?? (%d)", cmd); + return buf; +} + +/* + * Decode message arguments + */ +static void +NgArgs(int cookie, int cmd, int resp, void *args, int arglen) +{ + +switch (cookie) { +case NGM_GENERIC_COOKIE: + switch (cmd) { + case NGM_SHUTDOWN: + return; + case NGM_MKPEER: + { + struct ngm_mkpeer *const mkp = (struct ngm_mkpeer *) args; + + if (resp) + return; + NGLOGX(" type \"%s\"", mkp->type); + NGLOGX(" ourhook \"%s\"", mkp->ourhook); + NGLOGX(" peerhook \"%s\"", mkp->peerhook); + return; + } + case NGM_CONNECT: + { + struct ngm_connect *const ngc = (struct ngm_connect *) args; + + if (resp) + return; + NGLOGX(" path \"%s\"", ngc->path); + NGLOGX(" ourhook \"%s\"", ngc->ourhook); + NGLOGX(" peerhook \"%s\"", ngc->peerhook); + return; + } + case NGM_NAME: + { + struct ngm_name *const ngn = (struct ngm_name *) args; + + if (resp) + return; + NGLOGX(" name \"%s\"", ngn->name); + return; + } + case NGM_RMHOOK: + { + struct ngm_rmhook *const ngr = (struct ngm_rmhook *) args; + + if (resp) + return; + NGLOGX(" hook \"%s\"", ngr->ourhook); + return; + } + case NGM_NODEINFO: + return; + case NGM_LISTHOOKS: + return; + case NGM_LISTNAMES: + case NGM_LISTNODES: + return; + case NGM_TEXT_STATUS: + if (!resp) + return; + NGLOGX(" status \"%s\"", (char *) args); + return; + } + break; + +case NGM_TTY_COOKIE: + switch (cmd) { + case NGM_TTY_GET_HOTCHAR: + if (!resp) + return; + NGLOGX(" char 0x%02x", *((int *) args)); + return; + case NGM_TTY_SET_HOTCHAR: + NGLOGX(" char 0x%02x", *((int *) args)); + return; + } + break; + +case NGM_ASYNC_COOKIE: + switch (cmd) { + case NGM_ASYNC_CMD_GET_STATS: + { + struct ng_async_stat *const as = (struct ng_async_stat *) args; + + if (!resp) + return; + NGLOGX(" syncOctets = %lu", as->syncOctets); + NGLOGX(" syncFrames = %lu", as->syncFrames); + NGLOGX(" syncOverflows = %lu", as->syncOverflows); + NGLOGX(" asyncOctets = %lu", as->asyncOctets); + NGLOGX(" asyncFrames = %lu", as->asyncFrames); + NGLOGX(" asyncRunts = %lu", as->asyncRunts); + NGLOGX(" asyncOverflows = %lu", as->asyncOverflows); + NGLOGX(" asyncBadCheckSums = %lu", as->asyncBadCheckSums); + return; + } + case NGM_ASYNC_CMD_GET_CONFIG: + case NGM_ASYNC_CMD_SET_CONFIG: + { + struct ng_async_cfg *const ac = (struct ng_async_cfg *) args; + + if (!resp ^ (cmd != NGM_ASYNC_CMD_GET_CONFIG)) + return; + NGLOGX(" enabled %s", ac->enabled ? "YES" : "NO"); + NGLOGX(" acfcomp %s", ac->acfcomp ? "YES" : "NO"); + NGLOGX(" Async MRU %u", ac->amru); + NGLOGX(" Sync MRU %u", ac->smru); + NGLOGX(" ACCM 0x%08x", ac->accm); + return; + } + case NGM_ASYNC_CMD_CLR_STATS: + return; + } + break; + +case NGM_IFACE_COOKIE: + switch (cmd) { + case NGM_IFACE_GET_IFNAME: + return; + case NGM_IFACE_GET_IFADDRS: + return; + } + break; + + } + _NgDebugBytes(args, arglen); +} + +/* + * Dump bytes in hex + */ +void +_NgDebugBytes(const u_char * ptr, int len) +{ + char buf[100]; + int k, count; + +#define BYPERLINE 16 + + for (count = 0; count < len; ptr += BYPERLINE, count += BYPERLINE) { + + /* Do hex */ + snprintf(buf, sizeof(buf), "%04x: ", count); + for (k = 0; k < BYPERLINE; k++, count++) + if (count < len) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), "%02x ", ptr[k]); + else + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), " "); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " "); + count -= BYPERLINE; + + /* Do ASCII */ + for (k = 0; k < BYPERLINE; k++, count++) + if (count < len) + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), + "%c", isprint(ptr[k]) ? ptr[k] : '.'); + else + snprintf(buf + strlen(buf), + sizeof(buf) - strlen(buf), " "); + count -= BYPERLINE; + + /* Print it */ + NGLOGX("%s", buf); + } +} + diff --git a/lib/libnetgraph/internal.h b/lib/libnetgraph/internal.h new file mode 100644 index 0000000..1022183 --- /dev/null +++ b/lib/libnetgraph/internal.h @@ -0,0 +1,67 @@ + +/* + * internal.h + * + * Copyright (c) 1996-1999 Whistle Communications, Inc. + * All rights reserved. + * + * Subject to the following obligations and disclaimer of warranty, use and + * redistribution of this software, in source or object code forms, with or + * without modifications are expressly permitted by Whistle Communications; + * provided, however, that: + * 1. Any and all reproductions of the source or object code must include the + * copyright notice above and the following disclaimer of warranties; and + * 2. No rights are granted, in any manner or form, to use Whistle + * Communications, Inc. trademarks, including the mark "WHISTLE + * COMMUNICATIONS" on advertising, endorsements, or otherwise except as + * such appears in the above copyright notice or in the software. + * + * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY + * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS + * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. + * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES + * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING + * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Archie Cobbs <archie@whistle.com> + * + * $FreeBSD$ + * $Whistle: internal.h,v 1.5 1999/01/20 00:57:22 archie Exp $ + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/select.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> +#include <err.h> + +extern int _gNgDebugLevel; + +extern void (*_NgLog)(const char *fmt, ...); +extern void (*_NgLogx)(const char *fmt, ...); + +#define NGLOG (*_NgLog) +#define NGLOGX (*_NgLogx) + +extern void _NgDebugSockaddr(struct sockaddr_ng *sg); +extern void _NgDebugMsg(struct ng_mesg *msg); +extern void _NgDebugBytes(const u_char *ptr, int size); + diff --git a/lib/libnetgraph/msg.c b/lib/libnetgraph/msg.c new file mode 100644 index 0000000..7eda707 --- /dev/null +++ b/lib/libnetgraph/msg.c @@ -0,0 +1,206 @@ + +/* + * msg.c + * + * Copyright (c) 1996-1999 Whistle Communications, Inc. + * All rights reserved. + * + * Subject to the following obligations and disclaimer of warranty, use and + * redistribution of this software, in source or object code forms, with or + * without modifications are expressly permitted by Whistle Communications; + * provided, however, that: + * 1. Any and all reproductions of the source or object code must include the + * copyright notice above and the following disclaimer of warranties; and + * 2. No rights are granted, in any manner or form, to use Whistle + * Communications, Inc. trademarks, including the mark "WHISTLE + * COMMUNICATIONS" on advertising, endorsements, or otherwise except as + * such appears in the above copyright notice or in the software. + * + * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY + * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS + * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. + * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES + * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING + * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Archie Cobbs <archie@whistle.com> + * + * $FreeBSD$ + * $Whistle: msg.c,v 1.9 1999/01/20 00:57:23 archie Exp $ + */ + +#include <sys/types.h> +#include <stdarg.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_socket.h> + +#include "netgraph.h" +#include "internal.h" + +/* Next message token value */ +static int gMsgId; + +/* For delivering both messages and replies */ +static int NgDeliverMsg(int cs, const char *path, + const struct ng_mesg *hdr, const void *args, size_t arglen); + +/* + * Send a message to a node using control socket node "cs". + * Returns -1 if error and sets errno appropriately. + * If successful, returns the message ID (token) used. + */ +int +NgSendMsg(int cs, const char *path, + int cookie, int cmd, const void *args, size_t arglen) +{ + struct ng_mesg msg; + + /* Prepare message header */ + memset(&msg, 0, sizeof(msg)); + msg.header.version = NG_VERSION; + msg.header.typecookie = cookie; + msg.header.token = ++gMsgId; + msg.header.flags = NGF_ORIG; + msg.header.cmd = cmd; + snprintf(msg.header.cmdstr, NG_CMDSTRLEN + 1, "cmd%d", cmd); + + /* Deliver message */ + if (NgDeliverMsg(cs, path, &msg, args, arglen) < 0) + return (-1); + return(gMsgId); +} + +/* + * Send a message that is a reply to a previously received message. + * Returns -1 and sets errno on error, otherwise returns zero. + */ +int +NgSendReplyMsg(int cs, const char *path, + const struct ng_mesg *msg, const void *args, size_t arglen) +{ + struct ng_mesg rep; + + /* Prepare message header */ + rep = *msg; + rep.header.flags = NGF_RESP; + + /* Deliver message */ + return (NgDeliverMsg(cs, path, &rep, args, arglen)); +} + +/* + * Send a message to a node using control socket node "cs". + * Returns -1 if error and sets errno appropriately, otherwise zero. + */ +static int +NgDeliverMsg(int cs, const char *path, + const struct ng_mesg *hdr, const void *args, size_t arglen) +{ + u_char sgbuf[NG_PATHLEN + 3]; + struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf; + u_char *buf = NULL; + struct ng_mesg *msg; + int errnosv = 0; + int rtn = 0; + + /* Sanity check */ + if (args == NULL) + arglen = 0; + + /* Get buffer */ + if ((buf = malloc(sizeof(*msg) + arglen)) == NULL) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("malloc"); + rtn = -1; + goto done; + } + msg = (struct ng_mesg *) buf; + + /* Finalize message */ + *msg = *hdr; + msg->header.arglen = arglen; + memcpy(msg->data, args, arglen); + + /* Prepare socket address */ + sg->sg_family = AF_NETGRAPH; + snprintf(sg->sg_data, NG_PATHLEN + 1, "%s", path); + sg->sg_len = strlen(sg->sg_data) + 3; + + /* Debugging */ + if (_gNgDebugLevel >= 2) { + NGLOGX("SENDING %s:", + (msg->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE"); + _NgDebugSockaddr(sg); + _NgDebugMsg(msg); + } + + /* Send it */ + if (sendto(cs, msg, sizeof(*msg) + arglen, + 0, (struct sockaddr *) sg, sg->sg_len) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("sendto(%s)", sg->sg_data); + rtn = -1; + goto done; + } + +done: + /* Done */ + free(buf); /* OK if buf is NULL */ + errno = errnosv; + return (rtn); +} + +/* + * Receive a control message. + * + * On error, this returns -1 and sets errno. + * Otherwise, it returns the length of the received reply. + */ +int +NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path) +{ + u_char sgbuf[NG_PATHLEN + sizeof(struct sockaddr_ng)]; + struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf; + int len, sglen = sizeof(sgbuf); + int errnosv; + + /* Read reply */ + len = recvfrom(cs, rep, replen, 0, (struct sockaddr *) sg, &sglen); + if (len < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("recvfrom"); + goto errout; + } + if (path != NULL) + snprintf(path, NG_PATHLEN + 1, "%s", sg->sg_data); + + /* Debugging */ + if (_gNgDebugLevel >= 2) { + NGLOGX("RECEIVED %s:", + (rep->header.flags & NGF_RESP) ? "RESPONSE" : "MESSAGE"); + _NgDebugSockaddr(sg); + _NgDebugMsg(rep); + } + + /* Done */ + return (len); + +errout: + errno = errnosv; + return (-1); +} + diff --git a/lib/libnetgraph/netgraph.3 b/lib/libnetgraph/netgraph.3 new file mode 100644 index 0000000..dc9df04 --- /dev/null +++ b/lib/libnetgraph/netgraph.3 @@ -0,0 +1,211 @@ +.\" Copyright (c) 1996-1999 Whistle Communications, Inc. +.\" All rights reserved. +.\" +.\" Subject to the following obligations and disclaimer of warranty, use and +.\" redistribution of this software, in source or object code forms, with or +.\" without modifications are expressly permitted by Whistle Communications; +.\" provided, however, that: +.\" 1. Any and all reproductions of the source or object code must include the +.\" copyright notice above and the following disclaimer of warranties; and +.\" 2. No rights are granted, in any manner or form, to use Whistle +.\" Communications, Inc. trademarks, including the mark "WHISTLE +.\" COMMUNICATIONS" on advertising, endorsements, or otherwise except as +.\" such appears in the above copyright notice or in the software. +.\" +.\" THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND +.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO +.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, +.\" INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. +.\" WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY +.\" REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS +.\" SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. +.\" IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES +.\" RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING +.\" WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +.\" PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR +.\" SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY +.\" OF SUCH DAMAGE. +.\" +.\" Author: Archie Cobbs <archie@whistle.com> +.\" +.\" $FreeBSD$ +.\" $Whistle: netgraph.3,v 1.7 1999/01/25 07:14:06 archie Exp $ +.\" +.Dd January 19, 1999 +.Dt NETGRAPH 3 +.Os FreeBSD 3 +.Sh NAME +.Nm NgMkSockNode , +.Nm NgNameNode , +.Nm NgSendMsg , +.Nm NgRecvMsg , +.Nm NgSendData , +.Nm NgRecvData , +.Nm NgSetDebug , +.Nm NgSetErrLog +.Nd Netgraph user library +.Sh SYNOPSIS +.Fd #include <netgraph.h> +.Ft int +.Fn NgMkSockNode "const char *name" "int *csp" "int *dsp" +.Ft int +.Fn NgNameNode "int cs" "const char *path" "const char *fmt" "..." +.Ft int +.Fn NgSendMsg "int cs" "const char *path" "int cookie" "int cmd" "const void *arg" "size_t arglen" +.Ft int +.Fn NgSendMsgReply "int cs" "const char *path" "struct ng_mesg *msg" "const void *arg" "size_t arglen" +.Ft int +.Fn NgRecvMsg "int cs" "struct ng_mesg *rep" "size_t replen" "char *path" +.Ft int +.Fn NgSendData "int ds" "const char *hook" "const u_char *buf" "size_t len" +.Ft int +.Fn NgRecvData "int ds" "u_char *buf" "size_t len" "char *hook" +.Ft int +.Fn NgSetDebug "int level" +.Ft void +.Fn NgSetErrLog "void (*log)(const char *fmt, ...)" "void (*logx)(const char *fmt, ...)" +.Sh DESCRIPTION +These functions facilitate user-mode program participation in the kernel +.Xr netgraph 4 +graph-based networking system, by utilizing the netgraph +.Em socket +node type (see +.Xr ng_socket 8 ")." +.Pp +.Fn NgMkSockNode +should be called first, to create a new +.Em socket +type netgraph node with associated control and data sockets. If +.Fa name +is non-NULL, the node will have that global name assigned to it. +.Fa "*csp" +and +.Fa "*dsp" +will be set to the newly opened control and data sockets +associated with the node; either +.Fa "csp" +or +.Fa "dsp" +may be NULL if only one socket is desired. +.Pp +.Fn NgNameNode +assigns a global name to the node addressed by +.Fa path . +.Pp +.Fn NgSendMsg +sends a control message from the socket node associated with control socket +.Fa cs +to the node addressed by +.Fa path . +The +.Fa cookie +indicates how to interpret +.Fa cmd , +which indicates a specific command. +Extra argument data (if any) is specified by +.Fa arg +and +.Fa arglen . +The +.Fa cookie , +.Fa cmd , +and argument data are defined by the header file corresponding +to the type of the node being addressed. +.Pp +Use +.Fn NgSendMsgReply +to send reply to a previously received control message. +The original message header should be pointed to by +.Fa msg . +.Pp +.Fn NgRecvMsg +reads the next control message received by the node associated with +control socket +.Fa cs . +The message and any extra argument data must fit in +.Fa replen +bytes. +If +.Fa "path" +is non-NULL, it must point to a buffer of at least +.Dv "NG_PATHLEN + 1" +bytes, which will be filled in (and NUL terminated) with the path to +the node from which the message was received. +.Pp +.Fn NgSendData +writes a data packet out on the specified hook of the node corresponding +to data socket +.Fa ds . +The node must already be connected to some other node via that hook. +.Pp +.Fn NgRecvData +reads the next data packet (of up to +.Fa len +bytes) received by the node corresponding to data socket +.Fa ds +and stores it in +.Fa buf , +which must be large enough to hold the entire packet. If +.Fa "hook" +is non-NULL, it must point to a buffer of at least +.Dv "NG_HOOKLEN + 1" +bytes, which will be filled in (and NUL terminated) with the name of +the hook on which the data was received. +.Pp +.Fn NgSetDebug +and +.Fn NgSetErrLog +are used for debugging. +.Fn NgSetDebug +sets the debug level (if non-negative), and returns the old setting. +Higher debug levels result in more verbosity. The default is zero. +All debug and error messages are logged via the functions +specified in the most recent call to +.Fn NgSetErrLog . +The default logging functions are +.Xr vwarn 3 +and +.Xr vwarnx 3 . +.Pp +Note that +.Xr select 2 +can be used on the data and the control sockets to detect the presence of +incoming data and control messages, respectively. +Data and control packets are always written and read atomically, i.e., +in one whole piece. +.Pp +User mode programs must be linked with the +.Dv -lnetgraph +flag to link in this library. +.Sh INITIALIZATION +Netgraph is not part of the standard FreeBSD kernel. To enable it, +either your kernel must be compiled with ``options NETGRAPH'' +in the kernel configuration file, or else the +.Xr netgraph 4 +and +.Xr ng_socket 8 +KLD modules must have been loaded via +.Xr kldload 8 . +.Sh DIAGNOSTICS +All functions except +.Fn NgSetDebug +and +.Fn NgSetErrLog +return -1 if there was an error and set errno accordingly. +.Sh SEE ALSO +.Xr netgraph 4 , +.Xr socket 2 , +.Xr select 2 , +.Xr warnx 3 , +.Xr ng_socket 8 . +.Sh HISTORY +The +.Em netgraph +system was designed and first implemented at Whistle Communications, Inc. +in a version FreeBSD 2.2 customized for the Whistle InterJet. +.Sh AUTHOR +.An Archie Cobbs <archie@whistle.com> diff --git a/lib/libnetgraph/netgraph.h b/lib/libnetgraph/netgraph.h new file mode 100644 index 0000000..f60f04b --- /dev/null +++ b/lib/libnetgraph/netgraph.h @@ -0,0 +1,64 @@ + +/* + * netgraph.h + * + * Copyright (c) 1996-1999 Whistle Communications, Inc. + * All rights reserved. + * + * Subject to the following obligations and disclaimer of warranty, use and + * redistribution of this software, in source or object code forms, with or + * without modifications are expressly permitted by Whistle Communications; + * provided, however, that: + * 1. Any and all reproductions of the source or object code must include the + * copyright notice above and the following disclaimer of warranties; and + * 2. No rights are granted, in any manner or form, to use Whistle + * Communications, Inc. trademarks, including the mark "WHISTLE + * COMMUNICATIONS" on advertising, endorsements, or otherwise except as + * such appears in the above copyright notice or in the software. + * + * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY + * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS + * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. + * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES + * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING + * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Archie Cobbs <archie@whistle.com> + * + * $FreeBSD$ + * $Whistle: netgraph.h,v 1.7 1999/01/20 00:57:23 archie Exp $ + */ + +#ifndef _NETGRAPH_H_ +#define _NETGRAPH_H_ + +#include <sys/types.h> +#include <netgraph/ng_message.h> + +__BEGIN_DECLS +int NgMkSockNode(const char *, int *, int *); +int NgNameNode(int, const char *, const char *, ...); +int NgSendMsg(int, const char *, int, int, const void *, size_t); +int NgSendReplyMsg(int, const char *, + const struct ng_mesg *, const void *, size_t); +int NgRecvMsg(int, struct ng_mesg *, size_t, char *); +int NgSendData(int, const char *, const u_char *, size_t); +int NgRecvData(int, u_char *, size_t, char *); +int NgSetDebug(int); +void NgSetErrLog(void (*)(const char *fmt, ...), + void (*)(const char *fmt, ...)); +__END_DECLS + +#endif + diff --git a/lib/libnetgraph/sock.c b/lib/libnetgraph/sock.c new file mode 100644 index 0000000..b8bb9e6 --- /dev/null +++ b/lib/libnetgraph/sock.c @@ -0,0 +1,264 @@ + +/* + * sock.c + * + * Copyright (c) 1996-1999 Whistle Communications, Inc. + * All rights reserved. + * + * Subject to the following obligations and disclaimer of warranty, use and + * redistribution of this software, in source or object code forms, with or + * without modifications are expressly permitted by Whistle Communications; + * provided, however, that: + * 1. Any and all reproductions of the source or object code must include the + * copyright notice above and the following disclaimer of warranties; and + * 2. No rights are granted, in any manner or form, to use Whistle + * Communications, Inc. trademarks, including the mark "WHISTLE + * COMMUNICATIONS" on advertising, endorsements, or otherwise except as + * such appears in the above copyright notice or in the software. + * + * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND + * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, + * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY + * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS + * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. + * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES + * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING + * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Author: Archie Cobbs <archie@whistle.com> + * + * $FreeBSD$ + * $Whistle: sock.c,v 1.12 1999/01/20 00:57:23 archie Exp $ + */ + +#include <sys/types.h> +#include <stdarg.h> +#include <netgraph/ng_message.h> +#include <netgraph/ng_socket.h> + +#include "netgraph.h" +#include "internal.h" + +/* + * Create a socket type node and give it the supplied name. + * Return data and control sockets corresponding to the node. + * Returns -1 if error and sets errno. + */ +int +NgMkSockNode(const char *name, int *csp, int *dsp) +{ + char namebuf[NG_NODELEN + 1]; + int cs = -1; /* control socket */ + int ds = -1; /* data socket */ + int errnosv; + + /* Empty name means no name */ + if (name && *name == 0) + name = NULL; + + /* Create control socket; this also creates the netgraph node */ + if ((cs = socket(AF_NETGRAPH, SOCK_DGRAM, NG_CONTROL)) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("socket"); + goto errout; + } + + /* Assign the node the desired name, if any */ + if (name != NULL) { + u_char sbuf[NG_NODELEN + 3]; + struct sockaddr_ng *const sg = (struct sockaddr_ng *) sbuf; + + /* Assign name */ + snprintf(sg->sg_data, NG_NODELEN + 1, "%s", name); + sg->sg_family = AF_NETGRAPH; + sg->sg_len = strlen(sg->sg_data) + 3; + if (bind(cs, (struct sockaddr *) sg, sg->sg_len) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("bind(%s)", sg->sg_data); + goto errout; + } + + /* Save node name */ + snprintf(namebuf, sizeof(namebuf), "%s", name); + } else if (dsp != NULL) { + u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)]; + struct ng_mesg *const resp = (struct ng_mesg *) rbuf; + struct nodeinfo *const ni = (struct nodeinfo *) resp->data; + + /* Find out the node ID */ + if (NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, + NGM_NODEINFO, NULL, 0) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("send nodeinfo"); + goto errout; + } + if (NgRecvMsg(cs, resp, sizeof(rbuf), NULL) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("recv nodeinfo"); + goto errout; + } + + /* Save node "name" */ + snprintf(namebuf, sizeof(namebuf), "[%lx]", (u_long) ni->id); + } + + /* Create data socket if desired */ + if (dsp != NULL) { + u_char sbuf[NG_NODELEN + 4]; + struct sockaddr_ng *const sg = (struct sockaddr_ng *) sbuf; + + /* Create data socket, initially just "floating" */ + if ((ds = socket(AF_NETGRAPH, SOCK_DGRAM, NG_DATA)) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("socket"); + goto errout; + } + + /* Associate the data socket with the node */ + snprintf(sg->sg_data, NG_NODELEN + 2, "%s:", namebuf); + sg->sg_family = AF_NETGRAPH; + sg->sg_len = strlen(sg->sg_data) + 3; + if (connect(ds, (struct sockaddr *) sg, sg->sg_len) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("connect(%s)", sg->sg_data); + goto errout; + } + } + + /* Return the socket(s) */ + if (csp) + *csp = cs; + else + close(cs); + if (dsp) + *dsp = ds; + return (0); + +errout: + /* Failed */ + if (cs >= 0) + close(cs); + if (ds >= 0) + close(ds); + errno = errnosv; + return (-1); +} + +/* + * Assign a globally unique name to a node + * Returns -1 if error and sets errno. + */ +int +NgNameNode(int cs, const char *path, const char *fmt, ...) +{ + struct ngm_name ngn; + va_list args; + + /* Build message arg */ + va_start(args, fmt); + vsnprintf(ngn.name, sizeof(ngn.name), fmt, args); + va_end(args); + + /* Send message */ + if (NgSendMsg(cs, path, + NGM_GENERIC_COOKIE, NGM_NAME, &ngn, sizeof(ngn)) < 0) { + if (_gNgDebugLevel >= 1) + NGLOGX("%s: failed", __FUNCTION__); + return (-1); + } + + /* Done */ + return (0); +} + +/* + * Read a packet from a data socket + * Returns -1 if error and sets errno. + */ +int +NgRecvData(int ds, u_char * buf, size_t len, char *hook) +{ + u_char frombuf[NG_HOOKLEN + sizeof(struct sockaddr_ng)]; + struct sockaddr_ng *const from = (struct sockaddr_ng *) frombuf; + int fromlen = sizeof(frombuf); + int rtn, errnosv; + + /* Read packet */ + rtn = recvfrom(ds, buf, len, 0, (struct sockaddr *) from, &fromlen); + if (rtn < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("recvfrom"); + errno = errnosv; + return (-1); + } + + /* Copy hook name */ + if (hook != NULL) + snprintf(hook, NG_HOOKLEN + 1, "%s", from->sg_data); + + /* Debugging */ + if (_gNgDebugLevel >= 2) { + NGLOGX("READ %s from hook \"%s\" (%d bytes)", + rtn ? "PACKET" : "EOF", from->sg_data, rtn); + if (_gNgDebugLevel >= 3) + _NgDebugBytes(buf, rtn); + } + + /* Done */ + return (rtn); +} + +/* + * Write a packet to a data socket. The packet will be sent + * out the corresponding node on the specified hook. + * Returns -1 if error and sets errno. + */ +int +NgSendData(int ds, const char *hook, const u_char * buf, size_t len) +{ + u_char sgbuf[NG_HOOKLEN + sizeof(struct sockaddr_ng)]; + struct sockaddr_ng *const sg = (struct sockaddr_ng *) sgbuf; + int errnosv; + + /* Set up destination hook */ + sg->sg_family = AF_NETGRAPH; + snprintf(sg->sg_data, NG_HOOKLEN + 1, "%s", hook); + sg->sg_len = strlen(sg->sg_data) + 3; + + /* Debugging */ + if (_gNgDebugLevel >= 2) { + NGLOGX("WRITE PACKET to hook \"%s\" (%d bytes)", hook, len); + _NgDebugSockaddr(sg); + if (_gNgDebugLevel >= 3) + _NgDebugBytes(buf, len); + } + + /* Send packet */ + if (sendto(ds, buf, len, 0, (struct sockaddr *) sg, sg->sg_len) < 0) { + errnosv = errno; + if (_gNgDebugLevel >= 1) + NGLOG("sendto(%s)", sg->sg_data); + errno = errnosv; + return (-1); + } + + /* Done */ + return (0); +} + |