/* * arch_ip.cpp - arch specific udp/ip code. (linux ver) * added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c) */ #include #include /* for htons & co. */ #include #include #include #include #include #include extern "C" { #include "ipx_drv.h" #include "types.h" #include "mono.h" //#include "multi.h" } #include "ip_base.h" #include "ipclient.h" static int mysock=-1; /* Do hostname resolve on name "buf" and return the address in buffer "qhbuf". */ int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport) { struct hostent *he; char *s; char c=0; u_short p; if ((s=strrchr(buf,':'))) { c=*s; *s='\0'; p=ip_portshift(baseport,s+1); } else p=ip_portshift(baseport,NULL);//memset(qhbuf+4,0,2); he=gethostbyname((char *)buf); if (s) *s=c; if (!he) { msg("Error resolving my hostname \"%s\"",buf); return -1; //(NULL); } if (he->h_addrtype!=AF_INET || he->h_length!=4) { msg("Error parsing resolved my hostname \"%s\"",buf); return -1;//(NULL); } if (!*he->h_addr_list) { msg("My resolved hostname \"%s\" address list empty",buf); return -1;//(NULL); } addr->set(4,(u_char*)*he->h_addr_list,p); // memcpy(qhbuf,(*he->h_addr_list),4); // return(qhbuf); return 0; } #ifdef UDPDEBUG /* Like dumpraddr() but for structure "sockaddr_in" */ static void dumpaddr(struct sockaddr_in *sin) { unsigned short ports; u_char qhbuf[6]; memcpy(qhbuf+0,&sin->sin_addr,4); //ports=htons(((short)ntohs(sin->sin_port))-UDP_BASEPORT); ports=sin->sin_port; memcpy(qhbuf+4,&ports,2); dumpraddr(qhbuf); } #endif int ip_sendtoca(ip_addr addr,const void *buf,int len){ struct sockaddr_in toaddr; if (addr.addrlen()!=4) return 0;//not handled yet toaddr.sin_family=AF_INET; memcpy(&toaddr.sin_addr,addr.addr,4); toaddr.sin_port=*(unsigned short *)(addr.addr+4); #ifdef UDPDEBUG printf(MSGHDR "sendtoca((%d) ",len); //dumpraddr(addr.addr); addr.dump(); puts(")."); #endif return sendto(mysock,buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr)); } /* Find as much as MAX_BRDINTERFACES during local iface autoconfiguration. * Note that more interfaces can be added during manual configuration * or host-received-packet autoconfiguration */ #define MAX_BRDINTERFACES 16 /* We require the interface to be UP and RUNNING to accept it. */ #define IF_REQFLAGS (IFF_UP|IFF_RUNNING) /* We reject any interfaces declared as LOOPBACK type. */ #define IF_NOTFLAGS (IFF_LOOPBACK) int arch_ip_get_my_addr(u_short myport){ unsigned cnt=MAX_BRDINTERFACES,i,j; struct ifconf ifconf; int sock; struct sockaddr_in *sinp; ip_addr addr; if ((sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0) FAIL("Creating socket() failure during broadcast detection: %m"); #ifdef SIOCGIFCOUNT if (ioctl(sock,SIOCGIFCOUNT,&cnt)) { /* msg("Getting iterface count error: %m"); */ } else cnt=cnt*2+2; #endif chk(ifconf.ifc_req=(struct ifreq *)alloca((ifconf.ifc_len=cnt*sizeof(struct ifreq)))); if (ioctl(sock,SIOCGIFCONF,&ifconf)||ifconf.ifc_len%sizeof(struct ifreq)) { close(sock); FAIL("ioctl(SIOCGIFCONF) failure during broadcast detection: %m"); } cnt=ifconf.ifc_len/sizeof(struct ifreq); // chk(broads=malloc(cnt*sizeof(*broads))); // broadsize=cnt; for (i=j=0;isin_family!=AF_INET) continue; addr.set(4,(ubyte*)&sinp->sin_addr,htons(myport)); #ifdef UDPDEBUG printf(MSGHDR"added if "); addr.dump(); printf("\n"); #endif ip_my_addrs.add(addr); } return(0); } /*int arch_ip_get_my_addr(u_short myport){ char buf[256]; if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname"); ip_addr ip; if (ip.dns(buf,myport)) FAIL("Error querying my own hostname \"%s\"",buf); ip_my_addrs.add(ip); return 0; }*/ int arch_ip_open_socket(int port){ struct sockaddr_in sin; int val_one=1; if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) { mysock = -1; FAIL("socket() creation failed on port %d: %m",port); } if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,&val_one,sizeof(val_one))) { if (close(mysock)) msg("close() failed during error recovery: %m"); mysock=-1; FAIL("setsockopt(SO_BROADCAST) failed: %m"); } sin.sin_family=AF_INET; sin.sin_addr.s_addr=htonl(INADDR_ANY); sin.sin_port=htons(port); if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) { if (close(mysock)) msg("close() failed during error recovery: %m"); mysock=-1; FAIL("bind() to UDP port %d failed: %m",port); } return 0; } void arch_ip_close_socket(void) { if (mysock<0) { msg("close w/o open"); return; } if (close(mysock)) msg("close() failed on CloseSocket D1X ip socket %m"); mysock=-1; } int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){ struct sockaddr_in fromaddr; socklen_t fromaddrsize=sizeof(fromaddr); int size; static ip_addr ip_fromaddr; ip_addr *vptr=&ip_fromaddr; if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0) return -1; if (fromaddr.sin_family!=AF_INET) return -1; #ifdef UDPDEBUG printf(MSGHDR "recvfrom((%d-2=%d),",size,size-2); dumpaddr(&fromaddr); puts(")."); #endif ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port); memcpy(rd->src_node,&vptr,sizeof(ip_addr*)); return size; } int arch_ip_PacketReady(void) { return ipx_general_PacketReady(mysock); }