1/*
2**	BPALogin - lightweight portable BIDS2 login client
3**	Copyright (c) 2001-3 Shane Hyde, and others.
4**
5**  This program is free software; you can redistribute it and/or modify
6**  it under the terms of the GNU General Public License as published by
7**  the Free Software Foundation; either version 2 of the License, or
8**  (at your option) any later version.
9**
10**  This program is distributed in the hope that it will be useful,
11**  but WITHOUT ANY WARRANTY; without even the implied warranty of
12**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13**  GNU General Public License for more details.
14**
15**  You should have received a copy of the GNU General Public License
16**  along with this program; if not, write to the Free Software
17**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19*/
20
21#include "bpalogin.h"
22#include "bcmnvram.h"
23
24/*
25**  Main processing loop.  Logs in, handles heartbeats, and logs out on request
26**
27**  Returns - 0 - We are no longer connected, and should not retry.
28**            1 - We are no longer connnected and should retry.
29*/
30int mainloop(struct session * s)
31{
32	int err;
33	struct sockaddr_in listenaddr;
34	struct hostent * he;
35	int addrsize;
36
37    int rawSock = 0;
38    struct ifreq ifr;
39
40	if(!parse_parms(s,NULL))
41	{
42    	s->debug(1,"[ bpaclient ] : parameter read error" );
43        //usage();
44        exit(1);
45    }
46
47    s->debug(1,"parameter parsing:\n");
48    s->debug(1,"username = %s\n",s->username);
49    s->debug(1,"password = %s\n",s->password);
50    s->debug(1,"server   = %s\n",s->authserver);
51    s->debug(1,"minHB    = %d\n",s->minheartbeat);
52    s->debug(1,"maxHB    = %d\n",s->maxheartbeat);
53    s->debug(1,"localport= %d\n",s->localport);
54
55    if(!strcmp(s->username,""))
56    {
57        critical("Username has not been set");
58        exit(1);
59    }
60
61    if(!strcmp(s->password,""))
62    {
63        critical("Password has not been set");
64        exit(1);
65    }
66
67    /*
68     **  sleep until wanside get IP
69     */
70	if((rawSock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))<0)
71    	s->debug(1,"[ bpaclient ]: rawSock open error\n");
72
73    memset(&ifr,0,sizeof(struct ifreq));
74
75    /* Foxconn modified start, zacker, 10/22/2008, @qos_v8 */
76#if defined(U12H083)
77    strcpy(ifr.ifr_name,"eth0.2");
78#elif ( defined(U12H092) || defined(U12H155) )
79    strcpy(ifr.ifr_name,"eth0");
80#elif defined(U12H072) || defined(U12H114) || (defined U12H139) || defined(U12H127)
81    strcpy(ifr.ifr_name, nvram_safe_get("wan_ifname"));
82#else
83    strcpy(ifr.ifr_name,"eth1");
84#endif
85    /* Foxconn modified end, zacker, 10/22/2008, @qos_v8 */
86
87    do
88    {
89    	sleep(POLL_CYCLE);
90
91        if (ioctl(rawSock,  SIOCGIFADDR, &ifr)<0)
92        {
93        	s->debug(2,"ioctl error!!\n");
94            s->debug(2,"errno = %d\n",errno);
95        }
96
97        s->debug(2,"ipaddress of %s : %s\n",ifr.ifr_name,inet_ntoa(((struct sockaddr_in*)(&ifr.ifr_addr))->sin_addr));
98    }
99    while(!strcmp(inet_ntoa(((struct sockaddr_in*)(&ifr.ifr_addr))->sin_addr),"0.0.0.0"));
100
101	close(rawSock);
102
103	s->lastheartbeat = 0;
104	s->sequence = 0;
105	s->listensock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
106	s->debug(2,"listen socket = %d \n",s->listensock);//steve add for dbg
107	s->localaddr.sin_family = AF_INET;
108	s->localaddr.sin_port = htons(s->localport);
109
110	if(strcmp(s->localaddress,""))
111	{
112		s->debug(2,"Using local address %s\n",s->localaddress);
113		he = gethostbyname(s->localaddress);
114
115		if(he)
116		{
117			s->localaddr.sin_addr.s_addr = *((int*)(he->h_addr_list[0]));
118		}
119		else
120		{
121			s->localaddr.sin_addr.s_addr = inet_addr(s->localaddress);
122		}
123	}
124	else
125	{
126		s->localaddr.sin_addr.s_addr = INADDR_ANY;
127	}
128
129	addrsize = sizeof(struct sockaddr_in);
130	err = bind(s->listensock,(struct sockaddr *)&s->localaddr,sizeof(s->localaddr));
131	err = getsockname(s->listensock,(struct sockaddr *)&listenaddr,&addrsize);
132
133	s->sessionid = time(NULL);
134
135	s->listenport = ntohs(listenaddr.sin_port);
136	strcpy(s->osname,"whocares");
137	strcpy(s->osrelease,"notme");
138
139	he = gethostbyname(s->authserver);
140
141	if(he)
142	{
143		s->authhost.sin_addr.s_addr = *((int*)(he->h_addr_list[0]));
144	}
145	else
146	{
147		s->authhost.sin_addr.s_addr = inet_addr(s->authserver);
148	}
149
150	s->authhost.sin_port = htons(s->authport);
151	s->authhost.sin_family = AF_INET;
152
153	s->debug(1,"Auth host = %s:%d\n",s->authserver,s->authport);
154	s->debug(1,"Listening on port %d\n",s->listenport);
155
156	if(login(s))
157	{
158		s->onconnected(s->listenport);
159		if(!handle_heartbeats(s))
160		{
161		   /*
162		    **   heartbeat return 0:
163		    **   case 1 : login fail-->to sleep for LGIN_CYCLE sec
164		    **   case 2 : restart pkt is recv --> no implement: should reset state and do login
165		    */
166
167			int i;
168			s->ondisconnected(1);
169			s->noncritical("Sleeping for %d second\n",LGIN_CYCLE);
170
171			for(i=0; i<LGIN_CYCLE; i++)
172			{
173				if(s->shutdown)
174					return 0;
175				else
176					sleep(1);
177			}
178		}
179		else
180		{
181			closesocket(s->listensock);
182			return 0;
183		}
184		closesocket(s->listensock);
185	}
186	else
187	{
188		int i;
189		/* Foxconn added start, zacker, 07/18/2008 */
190		if (s->state == STATE_AWAIT_NEG_RESP)
191			logout(0, s);
192		/* Foxconn added end, zacker, 07/18/2008 */
193
194		s->noncritical("Sleeping for %d second\n",LGIN_CYCLE);
195
196		for(i=0; i<LGIN_CYCLE; i++)
197		{
198			if(s->shutdown)
199				return 0;
200			else
201				sleep(1);
202		}
203		closesocket(s->listensock);
204	}
205	return 1;
206}
207
208