📄 agentapi.c
字号:
/* $Id: agentapi.c,v 1.15 2001/09/08 16:51:58 jm Exp $ * API support routines for agents * * Dynamic hierarchial IP tunnel * Copyright (C) 1998-2001, Dynamics group * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. See README and COPYING for * more details. */#define DEBUG_FLAG 'P'#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/un.h>#include <unistd.h>#include <fcntl.h>#include <grp.h>#include <pwd.h>#include <sys/types.h>#include <sys/stat.h>#include <errno.h>#include <assert.h>#include "debug.h"#include "agentapi.h"/* defines */#define ASSERT assert/* Open unix domain socket for API using given parameters. * Parameters: * path - path for UNIX domain socket or NULL to assign unique * address in the abstract namespace * group_name - group for the socket * owner - owner of the socket * permissions - permissions for to socket * Returns socket descriptor or -1 on error. */int api_open_socket(char *path, char *group_name, char *owner, int permissions){#ifdef DYN_TARGET_LINUX struct group *grp; struct passwd *pwd; int s; dyn_api_sockaddr addr; socklen_t addrlen; int flags; /* create socket */ s = socket(AF_LOCAL, SOCK_DGRAM, 0); if (s < 0) { DEBUG(DEBUG_FLAG, "api_open_socket: socket failed %s\n", strerror(errno)); return s; } /* Set non-blocking */ flags = fcntl(s, F_GETFL, 0); if (flags == -1) { DEBUG(DEBUG_FLAG, "api_open_socket: fcntl F_GETFL failed: " "%s\n", strerror(errno)); return -1; } if (fcntl(s, F_SETFL, flags | O_NDELAY) == -1) { DEBUG(DEBUG_FLAG, "api_open_socket: fcntl F_SETFL failed: " "%s\n", strerror(errno)); return -1; } /* remove old api socket */ if (path != NULL && unlink(path) < 0 && errno != ENOENT) { DEBUG(DEBUG_FLAG, "api_open_socket: unlink failed: %s\n", strerror(errno)); return -1; } /* bind to address */ memset((char *) &addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; if (path == NULL) { addr.sun_path[0] = '\0'; snprintf(addr.sun_path + 1, sizeof(addr.sun_path) - 1, "dynamics-%i-%i", getpid(), (int) random()); addrlen = sizeof(addr.sun_family) + 1 + strlen(addr.sun_path + 1); } else { snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); addrlen = sizeof(addr.sun_family) + strlen(addr.sun_path); } if (bind(s, (struct sockaddr *) &addr, addrlen) < 0) { DEBUG(DEBUG_FLAG, "api_open_socket: bind failed: %s\n", strerror(errno)); return -1; } if (path == NULL) return s; if (permissions != 0) { /* Set permissions */ if (chmod(path, (mode_t) permissions) < 0) { DEBUG(DEBUG_FLAG, "api_open_socket: chmod failed: " "%s\n", strerror(errno)); return -1; } } if (group_name != NULL && owner != NULL) { grp = getgrnam(group_name); if (grp == NULL) { DEBUG(DEBUG_FLAG, "api_open_socket: getgrnam failed " "(group=%s)\n", group_name); return -1; } pwd = getpwnam(owner); if (pwd == NULL) { DEBUG(DEBUG_FLAG, "api_open_socket: getpwnam failed " "(user=%s)\n", owner); return -1; } if (chown(path, pwd->pw_uid, grp->gr_gid) < 0) { DEBUG(DEBUG_FLAG, "api_open_socket: chown failed: " "%s\n", strerror(errno)); return -1; } } return s;#else return -1;#endif}/* Receive API message from socket s. * Paramters: * s - socket * addr - storage for source address * addrlen - length of addr * msg - buffer for the message * Source address is stored in addr and message in msg. * Size of receive buffer for msg is in sz. * Returns 0 on success and -1 on error. */int api_receive(int s, dyn_api_sockaddr *addr, socklen_t *addrlen, struct api_msg *msg){ int n;#ifndef DYN_TARGET_WINDOWS int i; char *c;#endif ASSERT(s != -1); ASSERT(addr != NULL); ASSERT(msg != NULL); *addrlen = sizeof(dyn_api_sockaddr); n = recvfrom(s, (void *) msg, sizeof(struct api_msg), 0, (struct sockaddr *) addr, addrlen); if (n < 0) { DEBUG(DEBUG_FLAG, "api_receive: recvfrom failed: %s\n", strerror(errno)); return -1; }#ifndef DYN_TARGET_WINDOWS c = (char *) addr->sun_path; DEBUG(DEBUG_FLAG, "API Received %d bytes from ", n); for (i = 0; i < *addrlen; i++) { if (*c >= 32 && *c <= 126) { DEBUG(DEBUG_FLAG, "%c", *c); } else { DEBUG(DEBUG_FLAG, "<%02x>", *c); } c++; } DEBUG(DEBUG_FLAG, "\n");#endif if (n < API_MSG_FIXED_LEN || n < API_MSG_FIXED_LEN + msg->length || (msg->type != 1 && msg->type != 0 )) { /* message is not valid */ DEBUG(DEBUG_FLAG, "api_receive: invalid message\n"); return -1; } return 0;}/* Send an API message msg through socket s to addr. * Return -1 on error and 0 on success */int api_send(int s, dyn_api_sockaddr *addr, socklen_t addrlen, struct api_msg *msg){ int n; ASSERT(s != -1); ASSERT(addr != NULL); ASSERT(msg != NULL); ASSERT(msg->length < API_DATA_SIZE); n = sendto(s, (void *) msg, API_MSG_FIXED_LEN + msg->length, 0, (struct sockaddr *) addr, addrlen); if (n < 0) { DEBUG(DEBUG_FLAG, "api_send: sendto failed: %s\n", strerror(errno)); return -1; }#ifdef DYN_TARGET_LINUX DEBUG(DEBUG_FLAG, "API Sent %d/%d bytes to %s\n", n, API_MSG_FIXED_LEN + msg->length, addr->sun_path);#endif#ifdef DYN_TARGET_WINDOWS DEBUG(DEBUG_FLAG, "API Sent %d/%d bytes to %s:%d\n", n, API_MSG_FIXED_LEN + msg->length, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));#endif if (n != msg->length + API_MSG_FIXED_LEN) { return -1; } return 0;}int api_send_reply(int s, dyn_api_sockaddr *addr, socklen_t addrlen, int code, unsigned char *data, int datalen){ struct api_msg msg; ASSERT(datalen < API_DATA_SIZE); msg.type = API_REPLY_MSG; msg.code = code; msg.length = datalen; memcpy(msg.params, data, msg.length); return api_send(s, addr, addrlen, &msg);}/* Close a unix domain socket and unlink it */void api_close_socket(int s){#ifdef DYN_TARGET_LINUX dyn_api_sockaddr name; unsigned int len;#endif if (s < 0) return;#ifdef DYN_TARGET_LINUX len = sizeof(name); if (getsockname(s, (struct sockaddr *)&name, &len) == 0) unlink(name.sun_path);#endif close(s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -