From adc82a1e80759afba2cfae432d4ee1ca190be1f4 Mon Sep 17 00:00:00 2001 From: ru Date: Tue, 27 Jan 2004 20:25:14 +0000 Subject: [PATCH] - Added three new interfaces, NgAllocRecvMsg(), NgAllocRecvAsciiMsg(), and NgAllocRecvData(), that dynamically allocate buffer for a binary message, an ascii message, and a data packet, respectively. The size of the allocated buffer is equal to the socket's receive buffer size to guarantee that a message or a data packet is not truncated. - Get rid of the static size buffer in NgSendAsciiMsg(). OK'ed by: archie, julian --- lib/libnetgraph/Makefile | 3 +++ lib/libnetgraph/msg.c | 53 ++++++++++++++++++++++++++++++++------ lib/libnetgraph/netgraph.3 | 41 ++++++++++++++++++++++++++++- lib/libnetgraph/netgraph.h | 3 +++ lib/libnetgraph/sock.c | 18 +++++++++++++ 5 files changed, 109 insertions(+), 9 deletions(-) diff --git a/lib/libnetgraph/Makefile b/lib/libnetgraph/Makefile index 227da194708a..ff8a3be218aa 100644 --- a/lib/libnetgraph/Makefile +++ b/lib/libnetgraph/Makefile @@ -16,9 +16,12 @@ MLINKS+= netgraph.3 NgSendMsg.3 MLINKS+= netgraph.3 NgSendAsciiMsg.3 MLINKS+= netgraph.3 NgSendMsgReply.3 MLINKS+= netgraph.3 NgRecvMsg.3 +MLINKS+= netgraph.3 NgAllocRecvMsg.3 MLINKS+= netgraph.3 NgRecvAsciiMsg.3 +MLINKS+= netgraph.3 NgAllocRecvAsciiMsg.3 MLINKS+= netgraph.3 NgSendData.3 MLINKS+= netgraph.3 NgRecvData.3 +MLINKS+= netgraph.3 NgAllocRecvData.3 MLINKS+= netgraph.3 NgSetDebug.3 MLINKS+= netgraph.3 NgSetErrLog.3 diff --git a/lib/libnetgraph/msg.c b/lib/libnetgraph/msg.c index f89c27f284ee..90b6278a5315 100644 --- a/lib/libnetgraph/msg.c +++ b/lib/libnetgraph/msg.c @@ -91,13 +91,10 @@ NgSendMsg(int cs, const char *path, int NgSendAsciiMsg(int cs, const char *path, const char *fmt, ...) { - const int bufSize = 1024; - char replybuf[2 * sizeof(struct ng_mesg) + bufSize]; - struct ng_mesg *const reply = (struct ng_mesg *)replybuf; - struct ng_mesg *const binary = (struct ng_mesg *)reply->data; - struct ng_mesg *ascii; + struct ng_mesg *reply, *binary, *ascii; char *buf, *cmd, *args; va_list fmtargs; + int token; /* Parse out command and arguments */ va_start(fmtargs, fmt); @@ -139,17 +136,22 @@ NgSendAsciiMsg(int cs, const char *path, const char *fmt, ...) free(ascii); /* Get reply */ - if (NgRecvMsg(cs, reply, sizeof(replybuf), NULL) < 0) + if (NgAllocRecvMsg(cs, &reply, NULL) < 0) return (-1); /* Now send binary version */ + binary = (struct ng_mesg *)reply->data; if (++gMsgId < 0) gMsgId = 1; binary->header.token = gMsgId; if (NgDeliverMsg(cs, - path, binary, binary->data, binary->header.arglen) < 0) + path, binary, binary->data, binary->header.arglen) < 0) { + free(reply); return (-1); - return (binary->header.token); + } + token = binary->header.token; + free(reply); + return (token); } /* @@ -276,6 +278,24 @@ NgRecvMsg(int cs, struct ng_mesg *rep, size_t replen, char *path) return (-1); } +/* + * Identical to NgRecvMsg() except buffer is dynamically allocated. + */ +int +NgAllocRecvMsg(int cs, struct ng_mesg **rep, char *path) +{ + int len; + socklen_t optlen; + + optlen = sizeof(len); + if (getsockopt(cs, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1 || + (*rep = malloc(len)) == NULL) + return (-1); + if ((len = NgRecvMsg(cs, *rep, len, path)) < 0) + free(*rep); + return (len); +} + /* * Receive a control message and convert the arguments to ASCII */ @@ -321,3 +341,20 @@ NgRecvAsciiMsg(int cs, struct ng_mesg *reply, size_t replen, char *path) return (0); } +/* + * Identical to NgRecvAsciiMsg() except buffer is dynamically allocated. + */ +int +NgAllocRecvAsciiMsg(int cs, struct ng_mesg **reply, char *path) +{ + int len; + socklen_t optlen; + + optlen = sizeof(len); + if (getsockopt(cs, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1 || + (*reply = malloc(len)) == NULL) + return (-1); + if ((len = NgRecvAsciiMsg(cs, *reply, len, path)) < 0) + free(*reply); + return (len); +} diff --git a/lib/libnetgraph/netgraph.3 b/lib/libnetgraph/netgraph.3 index 852017019e48..108775e62754 100644 --- a/lib/libnetgraph/netgraph.3 +++ b/lib/libnetgraph/netgraph.3 @@ -35,16 +35,22 @@ .\" $FreeBSD$ .\" $Whistle: netgraph.3,v 1.7 1999/01/25 07:14:06 archie Exp $ .\" -.Dd January 19, 1999 +.Dd January 27, 2004 .Dt NETGRAPH 3 .Os .Sh NAME .Nm NgMkSockNode , .Nm NgNameNode , .Nm NgSendMsg , +.Nm NgSendAsciiMsg , +.Nm NgSendMsgReply , .Nm NgRecvMsg , +.Nm NgAllocRecvMsg , +.Nm NgRecvAsciiMsg , +.Nm NgAllocRecvAsciiMsg , .Nm NgSendData , .Nm NgRecvData , +.Nm NgAllocRecvData , .Nm NgSetDebug , .Nm NgSetErrLog .Nd netgraph user library @@ -71,12 +77,18 @@ .Ft int .Fn NgRecvMsg "int cs" "struct ng_mesg *rep" "size_t replen" "char *path" .Ft int +.Fn NgAllocRecvMsg "int cs" "struct ng_mesg **rep" "char *path" +.Ft int .Fn NgRecvAsciiMsg "int cs" "struct ng_mesg *rep" "size_t replen" "char *path" .Ft int +.Fn NgAllocRecvAsciiMsg "int cs" "struct ng_mesg **rep" "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 NgAllocRecvData "int ds" "u_char **buf" "char *hook" +.Ft int .Fn NgSetDebug "int level" .Ft void .Fo NgSetErrLog @@ -204,6 +216,15 @@ The length of the control message is returned. A return value of zero indicates that the socket was closed. .Pp The +.Fn NgAllocRecvMsg +function works exactly like +.Fn NgRecvMsg , +except that the buffer for a message is dynamically allocated +to guarantee that a message is not truncated. +The size of the buffer is equal to the socket's receive buffer size. +The caller is responsible for freeing the buffer when it is no longer required. +.Pp +The .Fn NgRecvAsciiMsg function works exactly like .Fn NgRecvMsg , @@ -222,6 +243,15 @@ version of the arguments (and the reply header argument length field will be adjusted). .Pp The +.Fn NgAllocRecvAsciiMsg +function works exactly like +.Fn NgRecvAsciiMsg , +except that the buffer for a message is dynamically allocated +to guarantee that a message is not truncated. +The size of the buffer is equal to the socket's receive buffer size. +The caller is responsible for freeing the buffer when it is no longer required. +.Pp +The .Fn NgSendData function writes a data packet out on the specified hook of the node corresponding to data socket @@ -252,6 +282,15 @@ The length of the packet is returned. A return value of zero indicates that the socket was closed. .Pp The +.Fn NgAllocRecvData +function works exactly like +.Fn NgRecvData , +except that the buffer for a data packet is dynamically allocated +to guarantee that a data packet is not truncated. +The size of the buffer is equal to the socket's receive buffer size. +The caller is responsible for freeing the buffer when it is no longer required. +.Pp +The .Fn NgSetDebug and .Fn NgSetErrLog diff --git a/lib/libnetgraph/netgraph.h b/lib/libnetgraph/netgraph.h index d0f402ca6aa0..4eb15bd8bd89 100644 --- a/lib/libnetgraph/netgraph.h +++ b/lib/libnetgraph/netgraph.h @@ -54,9 +54,12 @@ int NgSendAsciiMsg(int, const char *, const char *, ...) __printflike(3, 4); int NgSendReplyMsg(int, const char *, const struct ng_mesg *, const void *, size_t); int NgRecvMsg(int, struct ng_mesg *, size_t, char *); +int NgAllocRecvMsg(int, struct ng_mesg **, char *); int NgRecvAsciiMsg(int, struct ng_mesg *, size_t, char *); +int NgAllocRecvAsciiMsg(int, struct ng_mesg **, char *); int NgSendData(int, const char *, const u_char *, size_t); int NgRecvData(int, u_char *, size_t, char *); +int NgAllocRecvData(int, u_char **, char *); int NgSetDebug(int); void NgSetErrLog(void (*)(const char *fmt, ...), void (*)(const char *fmt, ...)); diff --git a/lib/libnetgraph/sock.c b/lib/libnetgraph/sock.c index 7485baa6830f..070abea9852d 100644 --- a/lib/libnetgraph/sock.c +++ b/lib/libnetgraph/sock.c @@ -242,6 +242,24 @@ NgRecvData(int ds, u_char * buf, size_t len, char *hook) return (rtn); } +/* + * Identical to NgRecvData() except buffer is dynamically allocated. + */ +int +NgAllocRecvData(int ds, u_char **buf, char *hook) +{ + int len; + socklen_t optlen; + + optlen = sizeof(len); + if (getsockopt(ds, SOL_SOCKET, SO_RCVBUF, &len, &optlen) == -1 || + (*buf = malloc(len)) == NULL) + return (-1); + if ((len = NgRecvData(ds, *buf, len, hook)) < 0) + free(*buf); + return (len); +} + /* * Write a packet to a data socket. The packet will be sent * out the corresponding node on the specified hook.