2 * $Source: /cvs/cvsroot/d2x/arch/linux/arch_ip.cpp,v $
5 * $Date: 2002-02-15 06:41:41 $
7 * arch_ip.cpp - arch specific udp/ip code. (linux ver)
8 * added 2000/02/07 Matt Mueller (some code borrowed from ipx_udp.c)
10 * $Log: not supported by cvs2svn $
11 * Revision 1.1 2002/02/06 09:22:41 bradleyb
12 * Adding d1x network code
22 #include <netinet/in.h> /* for htons & co. */
27 #include <sys/ioctl.h>
41 /* Do hostname resolve on name "buf" and return the address in buffer "qhbuf".
43 int arch_ip_queryhost(ip_addr *addr,char *buf,u_short baseport)
50 if ((s=strrchr(buf,':'))) {
53 p=ip_portshift(baseport,s+1);
55 else p=ip_portshift(baseport,NULL);//memset(qhbuf+4,0,2);
56 he=gethostbyname((char *)buf);
59 msg("Error resolving my hostname \"%s\"",buf);
62 if (he->h_addrtype!=AF_INET || he->h_length!=4) {
63 msg("Error parsing resolved my hostname \"%s\"",buf);
66 if (!*he->h_addr_list) {
67 msg("My resolved hostname \"%s\" address list empty",buf);
70 addr->set(4,(u_char*)*he->h_addr_list,p);
71 // memcpy(qhbuf,(*he->h_addr_list),4);
77 /* Like dumpraddr() but for structure "sockaddr_in"
80 static void dumpaddr(struct sockaddr_in *sin)
85 memcpy(qhbuf+0,&sin->sin_addr,4);
86 //ports=htons(((short)ntohs(sin->sin_port))-UDP_BASEPORT);
88 memcpy(qhbuf+4,&ports,2);
94 int ip_sendtoca(ip_addr addr,const void *buf,int len){
95 struct sockaddr_in toaddr;
96 if (addr.addrlen()!=4) return 0;//not handled yet
97 toaddr.sin_family=AF_INET;
98 memcpy(&toaddr.sin_addr,addr.addr,4);
99 toaddr.sin_port=*(unsigned short *)(addr.addr+4);
101 con_printf(CON_DEBUG, MSGHDR "sendtoca((%d) ",len);
102 //dumpraddr(addr.addr);
104 con_printf(CON_DEBUG, ").\n");
106 return sendto(mysock,buf,len,0,(struct sockaddr *)&toaddr,sizeof(toaddr));
109 /* Find as much as MAX_BRDINTERFACES during local iface autoconfiguration.
110 * Note that more interfaces can be added during manual configuration
111 * or host-received-packet autoconfiguration
114 #define MAX_BRDINTERFACES 16
116 /* We require the interface to be UP and RUNNING to accept it.
119 #define IF_REQFLAGS (IFF_UP|IFF_RUNNING)
121 /* We reject any interfaces declared as LOOPBACK type.
123 #define IF_NOTFLAGS (IFF_LOOPBACK)
125 int arch_ip_get_my_addr(u_short myport){
126 unsigned cnt=MAX_BRDINTERFACES,i,j;
127 struct ifconf ifconf;
129 struct sockaddr_in *sinp;
132 if ((sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
133 FAIL("Creating socket() failure during broadcast detection: %m");
136 if (ioctl(sock,SIOCGIFCOUNT,&cnt))
137 { /* msg("Getting iterface count error: %m"); */ }
142 chk(ifconf.ifc_req=(struct ifreq *)alloca((ifconf.ifc_len=cnt*sizeof(struct ifreq))));
143 if (ioctl(sock,SIOCGIFCONF,&ifconf)||ifconf.ifc_len%sizeof(struct ifreq)) {
145 FAIL("ioctl(SIOCGIFCONF) failure during broadcast detection: %m");
147 cnt=ifconf.ifc_len/sizeof(struct ifreq);
148 // chk(broads=malloc(cnt*sizeof(*broads)));
150 for (i=j=0;i<cnt;i++) {
151 if (ioctl(sock,SIOCGIFFLAGS,ifconf.ifc_req+i)) {
153 FAIL("ioctl(udp,\"%s\",SIOCGIFFLAGS) error: %m",ifconf.ifc_req[i].ifr_name);
155 if (((ifconf.ifc_req[i].ifr_flags&IF_REQFLAGS)!=IF_REQFLAGS)||
156 (ifconf.ifc_req[i].ifr_flags&IF_NOTFLAGS))
158 if (ioctl(sock,SIOCGIFDSTADDR,ifconf.ifc_req+i)) {
160 FAIL("ioctl(udp,\"%s\",SIOCGIFDSTADDR) error: %m",ifconf.ifc_req[i].ifr_name);
163 sinp=(struct sockaddr_in *)&ifconf.ifc_req[i].ifr_netmask ;
164 if (sinp->sin_family!=AF_INET) continue;
165 addr.set(4,(ubyte*)&sinp->sin_addr,htons(myport));
167 con_printf(CON_DEBUG, MSGHDR"added if ");
169 con_printf(CON_DEBUG, "\n");
171 ip_my_addrs.add(addr);
176 /*int arch_ip_get_my_addr(u_short myport){
178 if (gethostname(buf,sizeof(buf))) FAIL("Error getting my hostname");
181 if (ip.dns(buf,myport)) FAIL("Error querying my own hostname \"%s\"",buf);
185 int arch_ip_open_socket(int port){
186 struct sockaddr_in sin;
188 if ((mysock = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0) {
190 FAIL("socket() creation failed on port %d: %m",port);
192 if (setsockopt(mysock,SOL_SOCKET,SO_BROADCAST,&val_one,sizeof(val_one))) {
193 if (close(mysock)) msg("close() failed during error recovery: %m");
195 FAIL("setsockopt(SO_BROADCAST) failed: %m");
197 sin.sin_family=AF_INET;
198 sin.sin_addr.s_addr=htonl(INADDR_ANY);
199 sin.sin_port=htons(port);
201 if (bind(mysock,(struct sockaddr *)&sin,sizeof(sin))) {
202 if (close(mysock)) msg("close() failed during error recovery: %m");
204 FAIL("bind() to UDP port %d failed: %m",port);
209 void arch_ip_close_socket(void) {
211 msg("close w/o open");
215 msg("close() failed on CloseSocket D1X ip socket %m");
218 int arch_ip_recvfrom(char*outbuf,int outbufsize,struct ipx_recv_data *rd){
219 struct sockaddr_in fromaddr;
220 socklen_t fromaddrsize=sizeof(fromaddr);
222 static ip_addr ip_fromaddr;
223 ip_addr *vptr=&ip_fromaddr;
225 if ((size=recvfrom(mysock,outbuf,outbufsize,0,(struct sockaddr *)&fromaddr,&fromaddrsize))<0)
228 if (fromaddr.sin_family!=AF_INET) return -1;
231 con_printf(CON_DEBUG, MSGHDR "recvfrom((%d-2=%d),",size,size-2);
233 con_printf(CON_DEBUG, ").\n");
236 ip_fromaddr.set(4,(u_char*)&fromaddr.sin_addr,fromaddr.sin_port);
238 memcpy(rd->src_node,&vptr,sizeof(ip_addr*));
241 int arch_ip_PacketReady(void) {
242 return ipx_general_PacketReady(mysock);