📄 sock.cc
字号:
/* * PXE daemon - enable the remote booting of PXE enabled machines. * Copyright (C) 2000 Tim Hurman (kano@kano.org.uk) * * 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 2 * of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *//****************************************************************************** * sock.c - socket IO class defs * ******************************************************************************/#include "sock.h"#include <iostream>#ifndef _SOCKLEN_Ttypedef unsigned int socklen_t;#endif // _SOCKLEN_T/****************************************************************************** * Constructor * ******************************************************************************/Sock::Sock(LogFile *_log, const char *interface, uint16_t port){ iflist_t *start, *ptr, *prev, distinct; int listlen = 0; this->log = _log; listen_multi = 0; multi_sockfd = -1; sockfds = NULL; ifnum = 0; memset(&default_addr, 0, sizeof(default_addr)); // prepare if(port == 0) port = DEF_PORT; default_addr.sin_port = htons(port); start = GetIfList(); ptr = start; // see if the specified interface is available while(ptr != NULL) { listlen++; if(NULL != interface) if(strcmp(interface, ptr->if_name) == 0) break; ptr = ptr->next; } // if available, only bind to that if (ptr != NULL) { std::cout << "Only binding to interface " << ptr->if_name << "\n"; distinct.if_name = ptr->if_name; memcpy(&(distinct.if_addr), &(ptr->if_addr), sizeof(distinct.if_addr)); default_addr.sin_addr.s_addr = distinct.if_addr.s_addr; distinct.next = NULL; Open(&distinct, 1, port); } else // else all interfaces { std::cout << "Binding to all interfaces\n"; default_addr.sin_addr.s_addr = INADDR_BROADCAST; Open(start, listlen, port); } prev = ptr = start; while(ptr != NULL) { ptr = ptr->next; delete[] prev->if_name; delete prev; prev = ptr; } }/****************************************************************************** * GetIfList - get a list of all interfaces in the machine * ******************************************************************************/#ifndef HAVE_GETIFADDRSiflist_t *Sock::GetIfList(){ int tmp_sockfd; struct ifconf ifc; struct sockaddr_in tmp_addr; iflist_t *start, *ptr; int pos, len, lastlen; tmp_sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(tmp_sockfd == -1) throw new SysException(errno, "Sock::Sock:socket()"); lastlen=0; len=1024; while(1) { ifc.ifc_len = len; ifc.ifc_req = new(struct ifreq[len]); if(ioctl(tmp_sockfd, SIOCGIFCONF, &ifc) < 0) throw new SysException(errno, "Sock::Sock:ioctl()"); if(ifc.ifc_len <= len) break; lastlen = ifc.ifc_len; len += 10; delete[] ifc.ifc_req; } close(tmp_sockfd); // allocate the first in the linked list start = new iflist_t; start->next = NULL; ptr = start; /* go throught the struct and pick out the info */ pos=0; while(1) { ptr->if_name = new char[strlen(ifc.ifc_req[pos].ifr_name)+1]; strcpy(ptr->if_name, ifc.ifc_req[pos].ifr_name); std::cout << "Found interface " << ifc.ifc_req[pos].ifr_name << "\n"; // tidy this up, too many ops memcpy(&tmp_addr, &(ifc.ifc_req[pos].ifr_addr), sizeof(tmp_addr)); memcpy(&(ptr->if_addr), &(tmp_addr.sin_addr), sizeof(ptr->if_addr)); // do we leave now? pos++; if(((pos)*sizeof(struct ifreq)) >= (unsigned)ifc.ifc_len) break; // allocate the new item ptr->next = new iflist_t; ptr = ptr->next; ptr->next = NULL; } delete[] ifc.ifc_req; return(start);}#elseiflist_t *Sock::GetIfList(){ struct ifaddrs *ifap, *ifptr; struct sockaddr_in tmp_addr; iflist_t *start, *ptr, *prevptr; // get an interface list if(-1 == getifaddrs(&ifap)) { log->Event(LEVEL_INFO, "Sock::GetIfList", 1, "Unable to get interface list"); return(NULL); } // allocate the first in the linked list start = ptr = prevptr = NULL; // go through the list ifptr = ifap; for(ifptr = ifap; ifptr; ifptr = ifptr->ifa_next) { if(!(ifptr->ifa_addr) || AF_INET != ifptr->ifa_addr->sa_family) continue; ptr = new iflist_t; ptr->next = NULL; if(NULL == start) start = prevptr = ptr; else { prevptr->next = ptr; prevptr = ptr; } ptr->if_name = new char[strlen(ifptr->ifa_name)+1]; strcpy(ptr->if_name, ifptr->ifa_name); std::cout << "Found interface " << ifptr->ifa_name << "\n"; // tidy this up, too many ops memcpy(&tmp_addr, ifptr->ifa_addr, sizeof(tmp_addr)); memcpy(&(ptr->if_addr), &(tmp_addr.sin_addr), sizeof(ptr->if_addr)); ptr->next = NULL; } // free the interface list freeifaddrs(ifap); return(start);}#endif // HAVE_GETIFADDRS/****************************************************************************** * Destructor * ******************************************************************************/Sock::~Sock(){ Close(); delete[] sockfds; delete[] bind_addrs; ifnum = 0;}/****************************************************************************** * Destructor * ******************************************************************************/voidSock::SetDefAddr(uint32_t addr){ if((addr != 0) && (default_addr.sin_addr.s_addr != 0)) default_addr.sin_addr.s_addr = htonl(addr);}/****************************************************************************** * Open - open a socket bound to and addr and ready to listen on another * ******************************************************************************/intSock::Open(iflist_t *local_addrs, int listlen, const uint16_t port){ int tmp; struct servent *bootpc_port; iflist_t *lptr; int pos; /* initalise vars */ lptr = local_addrs; listen_multi = 0; listen_broad = 0; ifnum = listlen; /* sockfds */ sockfds = new int[ifnum]; bind_addrs = new struct sockaddr_in[ifnum]; /* get the port */ listenport = htons(port); bootpc_port = getservbyname(BOOTPC_NAME, "udp"); if(bootpc_port == NULL) throw new SysException(errno, "Sock::Open:getservbyname()"); clientport = bootpc_port->s_port; for(pos=0; lptr != NULL; pos++) { /* fill the structs */ bzero(&bind_addrs[pos], sizeof(bind_addrs[pos])); bind_addrs[pos].sin_family = AF_INET; bind_addrs[pos].sin_port = listenport; memcpy(&(bind_addrs[pos].sin_addr), &(lptr->if_addr), sizeof(bind_addrs[pos].sin_addr)); std::cout << "Binding to: " << inet_ntoa(bind_addrs[pos].sin_addr) << "\n"; /* create a socket */ sockfds[pos] = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sockfds[pos] == -1) throw new SysException(errno, "Sock::Open:socket()"); /* allow socket re-use */ tmp = 1; if(setsockopt(sockfds[pos], SOL_SOCKET, SO_REUSEADDR, (const char*)&tmp, sizeof(tmp)) == -1) throw new SysException(errno, "Sock::Open:setsockopt(REUSE)"); /* bind the socket to a specific local interface */ if(bind(sockfds[pos], (struct sockaddr*)&bind_addrs[pos], sizeof(bind_addrs[pos])) != 0) throw new SysException(errno, "Sock::Open:bind()"); /* report that we have bound the interface */ char *tmpbuf = new char[16]; sprintf(tmpbuf, "%d", port); log->Event(LEVEL_INFO, "Sock::Open", 4, "Bound to address:", inet_ntoa(lptr->if_addr), "Port:", tmpbuf); delete[] tmpbuf; /* move forward a position */ lptr = lptr->next; } /* return */ return(0);}/****************************************************************************** * JoinMulticast - join a multicast group * ******************************************************************************/intSock::JoinMulticast(uint32_t multi_addr){ unsigned char tchar; struct ip_mreq mreq; struct sockaddr_in local; if(listen_multi == 1) return(0); // already listening /* passed a null addr */ if(multi_addr == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -