/************************************************************************ * IRC - Internet Relay Chat, * Copyright (C) 2001 Hybrid Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: m_fdsend.c,v 1.10 2004/03/30 00:53:55 leeh Exp $ */ /* List of ircd includes from ../include/ */ #include "stdinc.h" #include "tools.h" #include "channel.h" #include "client.h" #include "ircd.h" #include "numeric.h" #include "s_log.h" #include "s_serv.h" #include "send.h" #include "whowas.h" #include "irc_string.h" #include "hash.h" #include "msg.h" #include "parse.h" #include "modules.h" #include #include #include #include #include #include #include #include static int m_fdsend(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]); struct Message fdsend_msgtab = { "FDSEND", 0, 0, 0, MFLG_SLOW, { //mg_not_oper, mg_unreg, mg_ignore, {m_hit, 1}, mg_ignore, {m_fdsend, 1} //mg_unreg, {m_fdsend, 1}, {m_fdsend, 1}, {m_fdsend, 1}, mg_ignore, {m_fdsend, 1} mg_unreg, {m_fdsend, 1}, {m_fdsend, 1}, mg_ignore, mg_ignore, {m_fdsend, 1} } }; mapi_clist_av1 m_fdsend_clist[] = { &fdsend_msgtab, NULL }; DECLARE_MODULE_AV1( /* The first argument is the name */ fdsend, /* The second argument is the function to call on load */ NULL, /* And the function to call on unload */ NULL, /* Then the MAPI command list */ m_fdsend_clist, /* Next the hook list, if we have one. */ NULL, /* Then the hook function list, if we have one */ NULL, /* And finally the version number of this module. */ "$Revision: 1.00 $"); static int m_fdsend(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; struct msghdr msg; struct sockaddr_un sun; unsigned char ccmsg[CMSG_SPACE(sizeof(int))]; struct cmsghdr *cmsg; struct iovec vec; int s; s = -1; /* Verify that they should be executing this command in the first place. */ if(!IsServer(source_p) && !IsOper(source_p) && !IsAdmin(source_p)) { // This should be a local connection. sendto_one(source_p, ":%s NOTICE %s : You do not have the appropriate access, go way.", me.name, source_p->name); sendto_wallops_flags(UMODE_WALLOP, &me, "Attempt to FDSEND [%s] by %s!%s@%s", parv[1], source_p->name, source_p->username, source_p->host); return 0; } /* If they are allowed to use this command, and haven't specified any parameters, tell them how to use it. */ if(parc < 3) { sendto_one(source_p, ":%s NOTICE %s :fdsend ", me.name, source_p->name); return 0; } /* Does this command belong on another server? If so, send it on its way. */ if((hunt_server(client_p, source_p, ":%s FDSEND %s %s", 1, parc, parv)) != HUNTED_ISME) { return 0; } /* They're authed and its for us. Find the client */ if((target_p = find_client(parv[1])) == NULL) { /* However, if it doesn't exist, tell them so. */ //sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, parv[1]); sendto_one(client_p, form_str(ERR_NOSUCHNICK), me.name, client_p->name, parv[1]); return 0; } /* * Are they trying to goaway a server, admin, or operator? if so, do nothing. * * This check is also duplicated in the channel messaging code, in case someone is goawayged, * but opers up afterwards (that really shouldn't happen, anyways. */ if(IsServer(target_p) || IsAdmin(target_p) || IsOper(target_p)) { sendto_one(client_p, ":%s NOTICE %s : Your attempt to FDSEND [%s] was rejected..", me.name, source_p->name, target_p->name); sendto_wallops_flags(UMODE_WALLOP, &me, "Rejected attempt to FDSEND [%s] by %s!%s@%s", target_p->name, source_p->name, source_p->username, source_p->host); return 0; } // Build the unix socket sockaddr memset(&sun, 0, sizeof(struct sockaddr_un)); sun.sun_family = AF_UNIX; strncpy(sun.sun_path, parv[2], sizeof(sun.sun_path) - 1); // Build the data vector vec.iov_base = " "; vec.iov_len = 1; // Build the msg header msg.msg_name = &sun; msg.msg_namelen = sizeof(struct sockaddr_un); msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = ccmsg; // File in the data aspect cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(int)); *(int*)CMSG_DATA(cmsg) = target_p->localClient->fd; // Complete msg header msg.msg_controllen = cmsg->cmsg_len; msg.msg_flags = 0; s = socket(AF_UNIX, SOCK_DGRAM, 0); if(s == -1) { sendto_one(client_p, ":%s NOTICE %s: Unable to create socket: [%s]", me.name, client_p->name, strerror(errno)); goto out; } if(connect(s, &sun, sizeof(struct sockaddr_un)) == -1) { sendto_one(client_p, ":%s NOTICE %s: Unable to connect to socket: [%s]", me.name, client_p->name, strerror(errno)); goto out; } if(sendmsg(s, &msg, 0) == -1) { sendto_one(client_p, ":%s NOTICE %s: Unable to send message: [%s]", me.name, client_p->name, strerror(errno)); goto out; } sendto_one(client_p, ":%s NOTICE %s: [%s] has been sent to %s", me.name, client_p->name, target_p->name, parv[2]); sendto_wallops_flags(UMODE_OPERWALL, &me, "FDSEND Called [%s] by %s!%s@%s", target_p->name, source_p->name, source_p->username, source_p->host); out: if(s != -1) close(s); return 0; }